|
| 1 | +#include <algorithm> |
| 2 | +#include <chrono> |
| 3 | +#include <iostream> |
| 4 | +#include <latch> |
| 5 | +#include <memory> |
| 6 | +#include <random> |
| 7 | +#include <thread> |
| 8 | +#include <vector> |
| 9 | + |
| 10 | +std::random_device rd; // Non-deterministic random number generator |
| 11 | +std::mt19937 gen(rd()); // Seed the generator |
| 12 | +std::uniform_int_distribution<> dist(1, 5); // Distribution for random wait time |
| 13 | + |
| 14 | +class TeamManager { |
| 15 | +public: |
| 16 | + TeamManager(int team_size, int number_of_teams) |
| 17 | + : team_size_(team_size) |
| 18 | + , number_of_teams_(number_of_teams) |
| 19 | + { |
| 20 | + latches_.reserve(number_of_teams_); |
| 21 | + for (int i = 0; i < number_of_teams_; ++i) { |
| 22 | + auto latch = std::make_shared<std::latch>(team_size_); |
| 23 | + latches_.push_back(latch); |
| 24 | + } |
| 25 | + } |
| 26 | + |
| 27 | + void member_arrives(int member_id, int team_id) { |
| 28 | + // Assign member to the chosen team, starting from team 1 to 4 |
| 29 | + std::cout << "Member " << member_id << " is assigned to Team " << team_id + 1 << "." << std::endl; |
| 30 | + latches_[team_id]->count_down(); |
| 31 | + } |
| 32 | + |
| 33 | + void wait_for_teams() { |
| 34 | + std::for_each(latches_.begin(), latches_.end(), [](const auto& latch) { latch->wait(); }); |
| 35 | + } |
| 36 | + |
| 37 | +private: |
| 38 | + int team_size_; |
| 39 | + int number_of_teams_; |
| 40 | + std::vector<std::shared_ptr<std::latch>> latches_; |
| 41 | +}; |
| 42 | + |
| 43 | +void member_thread(TeamManager& manager, int member_id, int team_id) { |
| 44 | + auto waitingTime = dist(gen); |
| 45 | + std::cout << "Member " << member_id << " is on the way... that will take " << waitingTime << " s." << std::endl; |
| 46 | + // Simulate random travel time |
| 47 | + std::this_thread::sleep_for(std::chrono::seconds(waitingTime)); |
| 48 | + |
| 49 | + manager.member_arrives(member_id, team_id); |
| 50 | +} |
| 51 | + |
| 52 | +int main() { |
| 53 | + const int team_size = 3; // Number of members required per team |
| 54 | + const int number_of_teams = 4; // Number of teams |
| 55 | + |
| 56 | + TeamManager manager(team_size, number_of_teams); |
| 57 | + |
| 58 | + std::cout << "Calling the team members..." << std::endl; |
| 59 | + |
| 60 | + // Create threads for members arriving |
| 61 | + std::vector<std::thread> members; |
| 62 | + for (int i = 0; i < team_size * number_of_teams; ++i) { |
| 63 | + members.emplace_back(member_thread, std::ref(manager), i + 1, i % number_of_teams); |
| 64 | + } |
| 65 | + |
| 66 | + std::cout << "Waiting for all team members to arrive and get assigned..." << std::endl; |
| 67 | + // Manager starts to wait, since now the "members are in the pipeline" |
| 68 | + manager.wait_for_teams(); |
| 69 | + |
| 70 | + // Join all member threads, i.e. start the actual arrival process, concurrently for all members |
| 71 | + for (auto& member : members) { |
| 72 | + member.join(); |
| 73 | + } |
| 74 | + |
| 75 | + std::cout << "All teams are ready to play! The game begins!" << std::endl; |
| 76 | + |
| 77 | + return 0; |
| 78 | +} |
0 commit comments