> Can this posix style CV be done using a semaphore (which can remember a signal)?.
Well, starting from Vista Win32 provides API to deal with convars. However, if you are just desperate to implement it yourself. Look at how it can get done
#define MAXCOUNT whatever
struct condvar {HANDLE mutex; HANDLE semapthore; HANDLE event; DWORD count; };
int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr)
{
struct condvar* target=(struct condvar*)cond;
target->mutex=CreateMutex(0,0,0);
target->semaphore=CreateSemaphore(0,0,MAXCOUNT,0);
target->event=CreateEvent(0,0,0,0);
target->count=0;
return 0;
}
int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex)
{
struct condvar* target=(struct condvar*) cond;
//check whether we own mutex (it can be done with undocumented ZwQeueryMutant()
//and return failure if we don’t. From now on we assume we are mutex owners
if(target->count==MAXCOUNT) return -1; //we don’t want to exceed maxcount for semaphore,do we…
target->count++;
ReleaseMutex(target->mutex);
WaitForSingleObject(target->semaphore,INFINITE);
if(!InterlockedDecrement(target->count))SetEvent(target->event);
return 0;
}
int pthread_cond_broadcast(pthread_cond_t *cond)
{
struct condvar* target=(struct condvar*) cond;
WaitForSingleObject(target->mutex,INFINITE);
if(target->count)
{
ReleaseSemaphore target->semaphore, target->count,0);
WaitForSingleObject(target->event,INFINITE);
}
ReleaseMutex(target->mutex);
return 0;
}
As you can see it yourself, there is no need for atomicity, let alone for PulseEvent(), in order to implement condvars on Windows…
Anton Bassov