#ifndef CPP11_BLOCKINGQUEUE_H #define CPP11_BLOCKINGQUEUE_H /////////////////////////////////////////////////////////////// // Cpp11-BlockingQueue.h - Thread-safe Blocking Queue // // ver 1.1 // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2015 // /////////////////////////////////////////////////////////////// /* * Package Operations: * ------------------- * This package contains one thread-safe class: BlockingQueue. * Its purpose is to support sending messages between threads. * It is implemented using C++11 threading constructs including * std::condition_variable and std::mutex. The underlying storage * is provided by the non-thread-safe std::queue. * * Required Files: * --------------- * Cpp11-BlockingQueue.h * * Build Process: * -------------- * devenv Cpp11-BlockingQueue.sln /rebuild debug * * Maintenance History: * -------------------- * ver 1.1 : 26 Jan 2015 * - added copy constructor and assignment operator * ver 1.0 : 03 Mar 2014 * - first release * * ToDo: * ----- * - add move constructor and move assignment */ #include #include #include #include #include #include #include template class BlockingQueue { public: BlockingQueue() {} BlockingQueue(const BlockingQueue&); BlockingQueue& operator=(const BlockingQueue&); T deQ(); void enQ(const T& t); size_t size(); private: std::queue q_; std::mutex mtx_; std::condition_variable cv_; }; template BlockingQueue::BlockingQueue(const BlockingQueue& bq) : q_(bq.q_) { /* can't copy mutex or condition variable, so use default members */ } template BlockingQueue& BlockingQueue::operator=(const BlockingQueue& bq) { if (this == &bq) return *this; q_ = bq.q_; /* can't assign mutex or condition variable so use target's */ return *this; } template T BlockingQueue::deQ() { std::unique_lock l(mtx_); if(q_.size() > 0) { T temp = q_.front(); q_.pop(); return temp; } // may have spurious returns so loop on !condition while (q_.size() == 0) cv_.wait(l, [this] () { return q_.size() > 0; }); T temp = q_.front(); q_.pop(); return temp; } template void BlockingQueue::enQ(const T& t) { { std::lock_guard l(mtx_); q_.push(t); } cv_.notify_one(); } template size_t BlockingQueue::size() { std::lock_guard l(mtx_); return q_.size(); } #endif