************ EventPair ************ This is a standard "ping-pong" problem exactly like Tweedledum and Tweedledee. For the mutex/CV solution, a single condition variable is sufficient. The ping-pong loop code (e.g., Handoff) is as follows: mx->Acquire(); cv->Signal(mx); cv->Wait(mx); mx->Release(); This is one case in which you do not need to "loop before you leap": it is the exception that proves the rule. In this case, there is only one thread waiting and one thread issuing the signal, and no condition that must be true (other than that the signal occurred). For the semaphore solution, two semaphores are needed to prevent one party from consuming its own signal (V). No mutex is needed. The semaphore code looks like this: othersem->V(); mysem->P(); For EventPair, the Wait() primitive exists just to prime the "ping" so there's a thread blocked to "pong". This code is easy (just P() or cv->Wait()). Also, for EventPair there needs to be some way to keep track of which semaphore is the "current" semaphore in handoff, and switch to the other semaphore after each handoff. For TweedleDum and TweedleDee, just put the code fragments above in a loop, one loop for Dee and one loop for Dum (make sure each loop Ps on its own semaphore and Vs on the other guy's. In the Mx/CV solution, the Mx acquire may be outside the loop. Note: for TweedleDum/TweedleDee, the problem with the sleep solution is "the missed wakeup problem", where one thread issues its wakeup before the other is asleep. Understand how the Mx/CV and semaphore solutions avoid this problem. *************** Barrier *************** Condition* slavecv, mastercv; Mutex* mx; int count Create(int n) { new slavecv, mastercv, and mx; count = n; } Wait() { mx->Acquire(); while (count) cv->Wait(mx); mx->Release(); } Arrive() { mx->Acquire(); count--; if (count == 0) mastercv->Signal(); slavecv->Wait(); mx->Release(); } Release() { slavecv->Broadcast(); count = n; }