1
0
Fork 0
This repository has been archived on 2021-11-03. You can view files and clone it, but cannot push or open issues or pull requests.
uni-m.cds-adv-prog/ex9.2/main.cpp

110 lines
2.4 KiB
C++
Executable File

#include <thread>
#include <string>
#include <iostream>
#include <queue>
#include <random>
#include <chrono>
#include <mutex>
#include <condition_variable>
/*
* 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<int>& 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<std::mutex> q_lock(q_mutex);
q.push(n);
// Notify one of the consumers
q_cv.notify_one();
}
}
void consumer( queue<int>& 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<std::mutex> 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<int> 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;
}