#include #include #include class SpScQueue { std::mutex mutex; std::deque queue; bool closed = false; std::condition_variable cond; public: void push(int x) { std::lock_guard lock{mutex}; queue.push_back(x); cond.notify_one(); } void close() { std::lock_guard lock{mutex}; closed = true; cond.notify_all(); /* * Important: The lock guard's destructor will unlock the mutex. * As per C++ 32.6.4.2.2 Class mutex [thread.mutex.class] paragraph 2, * is is valid for another thread (in this case the consumer) to destroy * the mutex before the unlock() returns. * Users have to make sure not to access any members after unlocking, * for example by moving the notify_all() out of the lock */ } // return false if closed and empty bool pop(int* out) { std::unique_lock lock{mutex}; while(queue.empty() && ! closed) cond.wait(lock); if(queue.empty()) return false; *out = queue.front(); queue.pop_front(); return true; } }; // producer borrows queue void producer(SpScQueue* queue) { for(int i = 0; i < 10; ++i) queue->push(i); queue->close(); } // consumer holds ownership of queue void consumer(std::unique_ptr&& queue) { int x; while(queue->pop(&x)) { // consume value x } queue.reset(); // delete queue }