#include #include #include #include #include #include #include #include /* * Compile with 'g++ -pthread a.cpp' */ using namespace std; std::mutex q_mutex; std::mutex cout_mutex; std::condition_variable q_cv; void producer1( queue& q, const int id ) { // Make sure our cout does not cross some other thread's cout cout_mutex.lock(); cout << "======================" << endl; cout << " Starting Producer " << id << endl; cout << "======================" << endl; cout_mutex.unlock(); random_device d; mt19937 mt(d()); int t_max = 3000; uniform_int_distribution<> distr(0., t_max); int n = 0; while (true) { n = distr(mt); this_thread::sleep_for(chrono::milliseconds(n)); // Make sure our cout does not cross some other thread's cout cout_mutex.lock(); cout << "Producer " << id << " : " << n << endl; cout_mutex.unlock(); // Lock q so we can push a new element std::unique_lock q_lock(q_mutex); q.push(n); // Notify one of the consumers q_cv.notify_one(); } } void consumer( queue& q, const int id ) { // Make sure our cout does not cross some other thread's cout cout_mutex.lock(); cout << "======================" << endl; cout << " Starting Consumer " << id << endl; cout << "======================" << endl; cout_mutex.unlock(); int b = 0; while ( true ) { { // Scope the lock of the queue std::unique_lock q_lock(q_mutex); while ( q.empty() ) { // Wait until we get a signal from the condition variable q_cv.wait(q_lock); } // Get a value and pop it off b = q.front(); q.pop(); } // Make sure our cout does not cross some other thread's cout cout_mutex.lock(); cout << " -- Consumer " << id << " : " << b << endl; cout_mutex.unlock(); // Slow down this thread to have a race between the consumers and the producers // This only works after we have successfully read an int this_thread::sleep_for(chrono::milliseconds(2000)); } } int main() { queue q; thread cons1( consumer, std::ref(q), 1 ) ; // make sure the consumer must have slept at least once this_thread::sleep_for(chrono::seconds(2)); thread prod( producer1, std::ref(q), 1); this_thread::sleep_for(chrono::seconds(5)); thread cons2( consumer, std::ref(q), 2) ; prod.join(); cons1.join(); cons2.join(); cout << "Finishing up" << endl; return 0; }