Race

In a car race, two teams participate, each with 3 drivers. Each team has its own pit, 4 mechanics, and a flag person (lollipop man). Each driver enters their team’s pit twice during the race to change tires. If the pit is occupied, the driver waits in front of the pit. After the driver stops at their position in the pit, the flag person lowers the flag and the four mechanics begin changing the wheels (of course, mechanics in both pits may be changing tires simultaneously). When a mechanic finishes their task, they notify the flag person. After all four mechanics have changed their respective wheels, the flag person raises the flag and releases the driver back into the race. It is assumed that the mechanics and the flag person must be ready to change tires throughout the entire race.

Task

Simulate a race of two teams, each with: 3 driver threads, 4 mechanic threads, 1 flag person thread. All of the above threads are created by the main program thread. Synchronize threads using monitors.

Anything not explicitly specified in the task may be solved in an arbitrary way.

main thread(){
   create 6 driver threads, 8 mechanic threads, and 2 lollipop man threads;
   mark the start of the race;
}

driver thread(){
   wait for race start;
   drive x milliseconds, where x is a random number between 2000 and 5000 ms;
   go to pit to change tires;
   drive (7000 - x) ms;
   go to pit to change tires;
   drive y milliseconds, where y is a random number between 2000 and 3000 ms;
   print finished race;
}

mechanic thread(){
   while the race is ongoing{
      wait until the flag person gives the signal that tires can be changed;
      change_wheel; // simulate by waiting z milliseconds, where z is random between 2000 and 4000 ms
      notify the lollipop man that the wheel has been changed;
   }
}

flag_person thread(){ // lollipop man
   while the race is ongoing{
      signal with the flag that the driver may enter to change tires;
      wait until the driver stops;
      lower the flag;
      wait until the mechanics change the wheels;
      raise the flag;
   }
}

"Sleeping" for a given number of milliseconds can be achieved using the function usleep(ms*1000), which delays program execution for the specified number of microseconds.