#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <chrono>
// Class representing a shared bathroom used by one party at a time
class Bathroom {
private:
int inside = 0; // Current number of people inside
const int capacity; // Max capacity of bathroom
std::string current_party = ""; // Party currently occupying the bathroom ("Democrat" or "Republican")
std::mutex mtx; // Mutex to protect shared state
std::condition_variable cv; // Condition variable for waiting and notifying threads
public:
// Constructor with max capacity
Bathroom(int maxCapacity) : capacity(maxCapacity) {}
// Thread calls this to enter the bathroom
void enter(int id, const std::string& party) {
std::unique_lock<std::mutex> lock(mtx); // Acquire the mutex
// Wait while the bathroom is either:
// 1. Occupied by the opposite party
// 2. Full (reached max capacity)
cv.wait(lock, [&]() {
return (current_party == "" || current_party == party) && inside < capacity;
});
// If the bathroom was empty, set the current party
if (current_party == "") {
current_party = party;
}
// Allow the thread to enter
inside++;
std::cout << party << " " << id << " entered. Inside: " << inside << "\n";
}
// Thread calls this to leave the bathroom
void leave(int id, const std::string& party) {
std::unique_lock<std::mutex> lock(mtx); // Acquire the mutex
inside--; // Decrement count as this person is leaving
std::cout << party << " " << id << " left. Inside: " << inside << "\n";
// If the last person left, reset the current party
if (inside == 0) {
current_party = "";
}
// Notify all waiting threads so they can check if they can enter now
cv.notify_all();
}
};
// Function representing a person trying to use the bathroom
void person(Bathroom& bathroom, int id, const std::string& party) {
bathroom.enter(id, party); // Try to enter
std::this_thread::sleep_for(std::chrono::milliseconds(200 + rand() % 300)); // Simulate usage time
bathroom.leave(id, party); // Exit
}
int main() {
Bathroom bathroom(3); // Bathroom can hold up to 3 people
std::vector<std::thread> threads;
// Simulate 10 people trying to enter, alternating between Democrat and Republican
for (int i = 0; i < 10; ++i) {
std::string party = (i % 2 == 0) ? "Democrat" : "Republican";
threads.emplace_back(person, std::ref(bathroom), i, party);
}
// Wait for all threads to finish
for (auto& t : threads) t.join();
return 0;
}