Events vs. Condition Variables

Started by
10 comments, last by Shannon Barber 20 years, 5 months ago
I learned to program Win32 first, so I have an affinity for events (and semaphores) over mutexes and condition variables. However, just about everything I read about condition variables states that they are a superior mechanism over events, often safety is reason cited. What is not explained, or what I do understand anyway, is why. My experience thus far would lead me to believe Win32 events are less error prone than Linux condition variables due to stronger guarantees and post-condition that events offer over condition variables. Win32 events synchronize themselves, you do not have to employ an additional mutex as you do with condition variables, and events are never spuriously awoken as condition variables may be. It is possible to lose the signal with both events and condition variables. If you signal an already signaled event, it does not double-bang. Only one "awakening" occurs (there is a bug in the comport code example on MSDN due to this). With condition variables, if no one is waiting on it when it is signal, the signal is lost. (This was the first bug I wrote using cd''s, I expected the signal to persist until it was waited on). There are solutions for both of these issues, with events you cannot rely on state at the time of the event, you have to check the state at the time of the awakening. e.g. keep reading characters from the comport until there are no more, don''t just read how many were available when the event was signaled. With condition variables, you have to check the condition (the variable that the ‘condition variable’ signals for) prior to waiting (to see if it''s ready now). Events have a couple of configuration options that tailor their behavior for several different uses. When the event auto-resets, it is atomically reset upon a wait and you are guaranteed that one and only one thread will be awoken. Condition variables do not make a ''there can only be one'' guarantee, and all waiting threads may contend for the mutex upon signaling. (This causes thread-thrashing and is problematic on latency sensitive systems and high-capacity servers using thread-pools. I suppose this is a QoI issue, condition variables could be implemented without awakening all the waiting threads for one-shot-signals, but posix does not require this.) If you desire the ‘signal and forget’ behavior of condition variables, there is a PulseEvent Win32 API call that behaves this way (if no threads are waiting on the event, the signal is lost). One functional difference, is that you can call pthread_cond_signal or pthread_cond_broadcast on any condition variable, whereas you must decide at creation whether an event is automatic (auto-reset, behaves like cond signal) or manual (behaves like cond broadcast). The Win32 method is to wait on more than one event if you need this behavior; an automatic event for single-shots, and a manual event for broadcast. That is why I think events are easier to use, and are a superior solution. Why do so many think that condition variables are better?
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Advertisement
For one thing: Win32 events aren''t very portable, and do very much influence the structure of the code. This in itself, is reason enough to consider them superior for many people. Events might be better on Windows, in most cases, I''m not sure.
Personally, I don''t see anything wrong with event style synchronization primitives. Most of the time people saying this kind of thing are refering to a paper by P. Brinch-Hansen in 1974(?). I think it was published by the ACM, but I don''t remember the title. Something about concurrent programming I think.

Essentially there are two objections that I remember. Number one is that using events for synchronization somehow depend on knowing the relative speed of the two synchronizing threads/processes. Don''t ask me to explain this one, I was an undergrad when I read it. Number two is that events are error prone because there is no explicit relationship between the event object and the data that it guards, so in large scale designs it is possible to forget to synchronize properly.

Sorry, not very much help, but it should be enough to do a search and find the original paper.
quote:CWizard
For one thing: Win32 events aren''t very portable, and do very much influence the structure of the code. This in itself, is reason enough to consider them superior for many people. Events might be better on Windows, in most cases, I''m not sure.


Aside from waiting on multiple events simutaneously (I have an idea on how to emulate this as well, but no implementation to back it up yet), I have written a wrapper around a condition variable that behaves very much like a Win32 event. I believe you could use two Win32 events (and a mutex) and emulate a condition variable as well.

...
quote:SiCrane
Essentially there are two objections that I remember. Number one is that using events for synchronization somehow depend on knowing the relative speed of the two synchronizing threads/processes. Don''t ask me to explain this one, I was an undergrad when I read it. Number two is that events are error prone because there is no explicit relationship between the event object and the data that it guards, so in large scale designs it is possible to forget to synchronize properly.

Sorry, not very much help, but it should be enough to do a search and find the original paper.


Why would you try to guard data with an event? I think that''s a strawman. "Egads! Booleans are no good for floating-point calculations!"

I did read something about having to know the relative speed of the processes, but no example was given. I was not able to think of an example where condition variables did not also bind the execution times together. I''ll try to track down more information about the relative speed issue.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
quote:Original post by Magmai Kai Holmlor
Why would you try to guard data with an event? I think that''s a strawman. "Egads! Booleans are no good for floating-point calculations!"


Because in 1974 there were very few synchronization primitives available. I want to say that the only other proven method was spin-locks, as this was in the days when only load and stores could be considered atomic operations on the processor. Try to keep things in perspective: this is the paper that introduced monitors. Hoare wouldn''t write about mutexes until a year later.
On past projects i''ve used mutex and other synchronization objects. I only used them for data protection between threaded acccess, but i suppose multithreaded signaling is a possiblity as well, the only issue i would think would be the blocking on the waiting thread for the signals and signal registeration still would run into race conditions.

Recently I''ve read Pratical Statecharts in C/C++ by Miro Samek. It really opened my eyes to event based programming techniques and the role of hiearchical state machines. I''ve had a chance to implement an engine based upon these techniques and I can see their power and simplicity. Events by their nature are mobile, easilty crossing boundaries between modules, threads, processes, computers, etc. That loose copuling, in conjunction with the active object programming techinques as outlined in the book, can greatly reduce the complexity of programs. One thing i''ve noticed is the inherit latency of event based systems. Even though they usually are simpler and more efficient than a traditional polled or slot/signal approach, they suffer from higher latencies. For most applicaitons, I dont think this is a major issue, and in all cases an event based implementation can be reduced down into a more direct slot/signal implementaiton, with the tradeoff in compleixty and size.

Defintely using mutex for multithreaded data protection is a good idea, as that is their function. However using these object to handle flow of control distributedly and asychonrously, proably is not the best technique. I''ve found events to fill that role more efficiently, from my limited expereince.

However for systems which require high performance and are
willing to sacrifice the loose coupling and simplicity which events provide, using those condition variables proably would be a better choice. But there is a point in which the additional complexity may outweight the performance gains.

-ddn
I prefer the three building blocks of:

- atomic compare/exchange
- counting semaphores
- monitors

You can easily build the others on top of this, if you need them.

I also prefer an OS that has native support for waiting for multiple of these at the same time, select() or poll() style. Thus, there''s something to be said for all of these (except compare/exchange) to be file descriptors. Or, under Windows, HANDLEs and WaitForMultipleObjects().

Btw: that''s one thing Windows NT got right: WaitForMultipleObjects(), and making all the synchronizable primitives except CRITICAL_SECTION be waitable with that same function, including the message queue!
enum Bool { True, False, FileNotFound };
quote:Original post by SiCrane
quote:Original post by Magmai Kai Holmlor
Why would you try to guard data with an event? I think that''s a strawman. "Egads! Booleans are no good for floating-point calculations!"


Because in 1974 there were very few synchronization primitives available. I want to say that the only other proven method was spin-locks, as this was in the days when only load and stores could be considered atomic operations on the processor. Try to keep things in perspective: this is the paper that introduced monitors. Hoare wouldn''t write about mutexes until a year later.


Oh, are these criticisms stale then? It''s very possible Win32 events do not work anything like the events around back then.

- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Finally found the paper (took me forever because I was off by year):

Per Brinch Hansen, Concurrent Programming Concepts, ACM Computing Surveys, Vol. 5, No. 4, December, 1973.
http://www.acm.org/pubs/articles/journals/surveys/1973-5-4/p223-hansen/

I believe you need to have an account with the ACM in order to get at the full text though.
quote:Original post by Magmai Kai Holmlor

Oh, are these criticisms stale then? It''s very possible Win32 events do not work anything like the events around back then.



Stale or not, people still refer to the darn paper.

This topic is closed to new replies.

Advertisement