typedef struct { u_int waiters_count_; // Count of the number of waiters. CRITICAL_SECTION waiters_count_lock_; // Serialize access to . enum { SIGNAL = 0, BROADCAST = 1, MAX_EVENTS = 2 }; HANDLE events_[MAX_EVENTS]; // Signal and broadcast event HANDLEs. } pthread_cond_t; int pthread_cond_init (pthread_cond_t *cv, const pthread_condattr_t *) { // Initialize the count to 0. cv->waiters_count_ = 0; // Create an auto-reset event. cv->events_[SIGNAL] = CreateEvent (NULL, // no security FALSE, // auto-reset event FALSE, // non-signaled initially NULL); // unnamed // Create a manual-reset event. cv->events_[BROADCAST] = CreateEvent (NULL, // no security TRUE, // manual-reset FALSE, // non-signaled initially NULL); // unnamed } int pthread_cond_wait (pthread_cond_t *cv, pthread_mutex_t *external_mutex) { // Avoid race conditions. EnterCriticalSection (&cv->waiters_count_lock_); cv->waiters_count_++; LeaveCriticalSection (&cv->waiters_count_lock_); // It's ok to release the here since Win32 // manual-reset events maintain state when used with // . This avoids the "lost wakeup" bug... LeaveCriticalSection (external_mutex); // Wait for either event to become signaled due to // being called or being called. int result = WaitForMultipleObjects (2, ev->events_, FALSE, INFINITE); EnterCriticalSection (&cv->waiters_count_lock_); cv->waiters_count_--; int last_waiter = result == WAIT_OBJECT_0 + BROADCAST && cv->waiters_count_ == 0; LeaveCriticalSection (&cv->waiters_count_lock_); // Some thread called . if (last_waiter) // We're the last waiter to be notified or to stop waiting, so // reset the manual event. ResetEvent (cv->events_[BROADCAST]); // Reacquire the . EnterCriticalSection (external_mutex, INFINITE); } int pthread_cond_broadcast (pthread_cond_t *cv) { // Avoid race conditions. EnterCriticalSection (&cv->waiters_count_lock_); int have_waiters = cv->waiters_count_ > 0; LeaveCriticalSection (&cv->waiters_count_lock_); if (have_waiters) SetEvent (cv->events_[BROADCAST]); } int pthread_cond_signal (pthread_cond_t *cv) { // Avoid race conditions. EnterCriticalSection (&cv->waiters_count_lock_); int have_waiters = cv->waiters_count_ > 0; LeaveCriticalSection (&cv->waiters_count_lock_); if (have_waiters) SetEvent (cv->events_[SIGNAL]); }