A condition variable is a threading abstraction which can help in implementing robust multi-threaded code. Condition variables are core features of Java (Object.wait, .notify, .notifyAll) and .NET (Monitor.Wait, .Pulse and .PulseAll) but we needed an implementation for Delphi. I couldn’t find one so we wrote my own. If you are interested in (using) the code, we made it publicly available on the following page:
Win32 Condition Variables and Monitors for Delphi
Comments are welcome.

8 Comments
Coincidentally (I presume), Per Brinch Hansen, the inventor of the monitor concept, died less than a week before your release.
Thanks, guys. After two years of multithread development with c+pthreads and then Ada I have found Delphi’s parallel features to be, less to say, toys. I can hardly use events as freely as I was using condvars. It’s a pity that I can’t do current development in Ada: our systems are heavily tied on ADO.
I’ve noticed one mistake pinning out of ThreadDemo.dpr source code:
finally
FLock.Leave;
end;
FEmpty.PulseAll;
and the same in the Put():
finally
FLock.Leave;
end;
FFull.PulseAll;
Don’t do like this! From what I know about pthreads, it is a bounded error. One must signal on condvar only when mutex is owned.
E. g. “FEmpty.PulseAll;” must be placed before finally. I just hope there are no bounded errors in the Threads.pas itself.
Hello Ivan,
If I recall correctly, both variants are correct (putting the PulseAll in or after the try/finally block) for the Threads.pas implementation. PulseAll doesn’t use the external lock for synchronization, so it shouldn’t matter which variant you choose. Threads.pas is basically a port of pthreads for win32 which doesn’t require this either (also see ftp://sourceware.org/pub/pthreads-win32/sources/pthreads-w32-2-8-0-release/pthread_cond_signal.c), so it should be safe.
Producer might Pulse condvar when consumer has owned mutex but is not waiting on condvar yet. Consumer will have to wait the whole timeout or infinitelly.
Timeout in ThreadsDemo is 250 so it won’t cause serious problems in this particular case.
I’ve found a discussion on this topic:
http://thread.gmane.org/gmane.os.ecos.general/13018
Thanks the link Ivan, I will look into it. As far as I understand it, the PulseAll is not required to be inside the lock (according to the pthreads implementation).
To your comment above, the producer signals the condition variable only when the related predicate/condition is already true. It actually shouldn’t matter at all (performance differences aside as mentioned by your discussion) if the signal is issued within the lock or after - except if the internal implementation requires holding the lock.
While the producer adds an item to the queue, the whole section is locked and the client cannot enter the same lock. Once the item has been added, the mutex is unlocked and the consumer can enter the critical section. Since the condition is true, it shouldn’t matter if the producer is preempted right before signaling the condition variable because the consumer does not wait anyway.
Being able to signal the condition variable after releasing the lock seems to be an implementation specific feature since in Java and .NET, for example, you are required to hold the lock while signaling the condition variable. The new condition variable API which ships with Windows Vista, on the other hand, supports this feature as well (See SleepConditionVariableCS and WakeConditionVariable):
As a side note, I just learned that the new Delphi 2009 finally got support for condition variables with a new TMonitor record. Also, if you are developing against Windows Vista, it’s probably a better idea to directly use their new condition variable API.