#include #include #include #include #include #include // I love C++ using namespace std; const int MAX_SIZE{5}; counting_semaphore queueEmpty(MAX_SIZE); counting_semaphore queueFull(0); binary_semaphore queueMutex(1); binary_semaphore outputMutex(1); queue Q; void Consumer(int id); void Producer(ArgT * arg); void PostMessage(string message, int id); void Print(string message); int emptyCount {MAX_SIZE}; int fullCount{0}; int main() { int producers{4}; int consumers{3}; int messages{6}; vector producerThreads; vector consumerThreads; // make the producers for(int i =0; i < producers; ++i) { producerThreads.emplace_back(Producer, i, messages); } // make the consumers for(int i =0; i < consumers; ++i) { consumerThreads.emplace_back(Consumer, i+100); } // collect all of the producers for(auto & thread: producerThreads) { if(thread.joinable()) { thread.join(); } } // send a message to all of the consumers to get them to exit for(int i = 0; i < consumers; ++i) { PostMessage("done", 0); } // collect all of the consumers for(auto & thread: consumerThreads) { if(thread.joinable()) { thread.join(); } } return(0); } string GetMessage(int id ) { queueFull.acquire(); queueMutex.acquire(); emptyCount ++; fullCount --; Print("\t" + to_string(id) + "\tGot a message, empty " + to_string(emptyCount) + " full " + to_string(fullCount)); string message = Q.front(); Q.pop(); queueMutex.release(); queueEmpty.release(); return message; } void Print(string message) { outputMutex.acquire(); cout << message << endl; outputMutex.release(); } void Consumer(int id) { bool done{false}; string message; while(not done) { Print("\t" + to_string(id) + "\t is sleeping "); usleep(rand() % 1000); Print("\t" + to_string(id) + "\t is getting a message "); message = GetMessage(id); if (message == "done") { done = true; Print("\t" + to_string(id) + "\t is exiting"); } else { Print("\t" + to_string(id) + "\t got \"" + message + '"' ); } } } void PostMessage(string message, int id) { queueEmpty.acquire(); queueMutex.acquire(); Q.push(message); emptyCount --; fullCount ++; Print(to_string(id) + "\t\tPosted a message, empty " + to_string(emptyCount) + " full " + to_string(fullCount)); queueMutex.release(); queueFull.release(); } void Producer(int id, int iterations) { string message; for(int i = 0; i < iterations; ++i) { Print(to_string(id) + " is sleeping "); usleep(rand() % 500); message = "message " + to_string(i+1) + " from " + to_string(id); Print("\t" + to_string(id) + " is posting a message "); PostMessage(message, id); } Print("\t" + to_string(id) + " is all done, byby"); }