#pragma once #include #include template class BlockingQueue { std::deque deque{}; pthread_mutex_t lock; pthread_cond_t cond; public: BlockingQueue() : lock(PTHREAD_MUTEX_INITIALIZER), cond(PTHREAD_COND_INITIALIZER) {} ~BlockingQueue(); T take(); T &front(); T &back(); void put(const T&); void put(T&&); template< class... Args > void emplace_back(Args&&... args); void clear(); }; template BlockingQueue::~BlockingQueue() { pthread_mutex_destroy(&lock); pthread_cond_destroy(&cond); } template T BlockingQueue::take() { pthread_mutex_lock(&lock); while (deque.empty()) pthread_cond_wait(&cond, &lock); T ret(std::move(deque.front())); deque.pop_front(); pthread_mutex_unlock(&lock); return ret; } template void BlockingQueue::put(const T &s) { pthread_mutex_lock(&lock); deque.push_back(s); pthread_cond_signal(&cond); pthread_mutex_unlock(&lock); } template void BlockingQueue::put(T &&s) { pthread_mutex_lock(&lock); deque.push_back(std::move(s)); pthread_cond_signal(&cond); pthread_mutex_unlock(&lock); } template T &BlockingQueue::front() { return deque.front(); } template T &BlockingQueue::back() { return deque.back(); } template template void BlockingQueue::emplace_back(Args &&... args) { pthread_mutex_lock(&lock); deque.emplace_back(std::forward(args)...); pthread_cond_signal(&cond); pthread_mutex_unlock(&lock); } template void BlockingQueue::clear() { std::deque t; deque.swap(t); }