I implemented, somewhat closely based on this implementation, a blocking queue with emphasis on filling up first. So if one producer and one consumer thread are using the queue, the producing queue gets prioritized.Code// BQueue.hpp//#pragma once#ifndef _BQUEUE_HPP#define _BQUEUE_HPP#include <condition_variable>#include <mutex>#include <queue>template <class T> class BQueue {public:  BQueue(size_t size);  void push(T item);  bool pop(T &item);  /* ALTERNATIVE 1  void push(std::unique_ptr<T> item);  bool pop(std::unique_ptr<T> &item);  */private:  std::mutex _mutex;  //std::queue<std::unique_ptr<T>> _queue; // ALTERNATIVE 1  std::queue<T> _queue;  size_t _size;  std::condition_variable _condition_full;  std::condition_variable _condition_empty;};#include BQueue.hxx#endif // _BQUEUE_HPPimplementation// BQueue.hxx#include BQueue.hpp#include <condition_variable>#include <cstdlib>#include <iostream>#include <mutex>#include <queue>template <class T> BQueue<T>::BQueue(size_t size) : _size(size) {}// ALTERNATIVE 1// template <class T> void BQueue<T>::push(std::unique_ptr<T> item) {template <class T> void BQueue<T>::push(T item) {  std::unique_lock<std::mutex> lock(_mutex);  while (_queue.size() >= _size) {    _condition_full.wait(lock, [&]() { return (_queue.size() < _size); });  }  _queue.push(std::move(item));  // _queue.push(item); // ALTERNATIVE 1  // if queue is full, notify consumation part first  if (_queue.size() >= _size) {    _condition_empty.notify_one();  }  _condition_full.notify_one();}// template <class T> bool BQueue<T>::pop(T &item) {template <class T> bool BQueue<T>::pop(T &item) {  std::unique_lock<std::mutex> lock(_mutex);  while (_queue.empty()) {    if (!_condition_empty.wait_for(lock, std::chrono::seconds(1),                                   [&]() { return !_queue.empty(); })) {      // waited too long for input.      return false;    }  }  item = std::move(_queue.front());  // item = _queue.fron(); // ALTERNATIVE  _queue.pop();  /* THIS FOLLOWING CODE MAY BE NEEDED;   * KEEP IT IN CASE   * _condition_empty.notify_one();   * // if queue is empty, notify production   * if (_queue.empty()) { //*/  _condition_full.notify_one();  // assert(_queue.size() < _size); //*/  return true;}main// alternatively: class Resourcestruct Resource {  int x;};int main() {  BQueue<std::unique_ptr<struct Resource>> q{40};  //BQueue<struct Resource> q_alternative1[40};  std::unique_ptr<struct Resource> res1{new struct Resource};  res1->x = 42;  q.push(std::move(res1));  q.push(std::move(std::unique_ptr<struct Resource>{new struct Resource}));  for (size_t i = 0; i < 30; i++) {    std::unique_ptr<struct Resource> res{new struct Resource};    res->x = i;    q.push(std::move(res));  }  for (size_t i = 0; i < 15; i++)    q.pop(res1);  return 0;}Now, I came across the question of resource handling. What does make more sense? Using the shown code or implement the whole thing using std::unique_ptr where necessary (see ALTERNATIVE 1)? std::move even works with non-resource wrapped types, apparently..And, is the main function leak free? Or did I miss anything? Does it work for shared_ptr types as well, or do I have to specialize because of pop(T item &) being a reference?
Blocking Queue implementation with std::unique_ptr
c++;c++11;concurrency;queue