/////////////////////////////////////////////////////////////// // ConditionVariable.cpp - Blocking Queue // // // // Jim Fawcett, CSE687 - Object Oriented Design, Spring 2013 // /////////////////////////////////////////////////////////////// #include #include #include #include #include #include #include template class BlockingQueue { public: BlockingQueue() {} T deQ(); void enQ(const T& t); size_t size(); private: BlockingQueue(const BlockingQueue&); BlockingQueue& operator=(const BlockingQueue&); std::queue q_; std::mutex mtx_; std::condition_variable cv_; }; template T BlockingQueue::deQ() { std::unique_lock l(mtx_); if(q_.size() > 0) { T temp = q_.front(); q_.pop(); return temp; } // loop needed due to spurious returns from wait 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(); } std::mutex ioLock; void test(BlockingQueue* pQ) { std::string msg; do { msg = pQ->deQ(); { std::lock_guard l(ioLock); std::cout << "\n thread deQed " << msg.c_str(); } std::this_thread::sleep_for(std::chrono::milliseconds(3)); } while(msg != "quit"); } int main() { BlockingQueue q; std::thread t(test, &q); for(int i=0; i<25; ++i) { std::ostringstream temp; temp << i; std::string msg = std::string("msg#") + temp.str(); { std::lock_guard l(ioLock); std::cout << "\n main enQing " << msg.c_str(); } q.enQ(msg); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } t.join(); }