#include <mutex>
#include <condition_variable>
#include <deque>
class SpScQueue
{
std::mutex mutex;
std::deque<int> queue;
bool closed = false;
std::condition_variable cond;
public:
void push(int x)
{
std::lock_guard<std::mutex> lock{mutex};
queue.push_back(x);
cond.notify_one();
}
void close()
{
std::lock_guard<std::mutex> 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<std::mutex> 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<SpScQueue>&& queue)
{
int x;
while(queue->pop(&x)) {
// consume value x
}
queue.reset(); // delete queue
}
Comments
0 B
|0 👍
/0 👎
0 B
|👍
/👎