views:

668

answers:

3

I've recently seen the light of EventWaitHandle's powerful behavior in C# and decided to move some functionality in a sister application to do the same. The only problem is that the sister app is written in C.

No big deal, I'm using pthreads, which have a pthread_cond_t datatype that allows for signalling. My only question is, is it possible for a cond to be 'signalled' before something is waiting on it?

Right now my testing says no. That is, if ThreadA fires a signal before ThreadB is waiting, ThreadB will wait indefinately. Is there another pthread type that I can use that behaves closer to the functionality of the EventWaitHandle in C#? An object is signalled, meaning that the first thread to wait on it, will pass immediately, and set it to unsignalled.

Wrapping the pthread_cond into another data structure wouldn't be too hard to achieve this. But again, is this functionality already available in the pthread library?

+2  A: 

If you're using condition variables correctly, this won't matter.

The basic flow of your code should be (in pseudocode):

lock(lockobj);
while (!signalled) {
    wait(condvar);
}
signalled = false;
unlock(lockobj);

on the waiting side, and:

lock(lockobj);
signalled = true;
notify(condvar);
unlock(lockobj);

on the signalling side. (Of course, the lock object and condition variable used have to be the same on both sides.) Hope this helps!

Chris Jester-Young
that could result in a deadlock if the waiting thread locked before the signal was sent... would it not?
Nicholas Mancuso
No, remember that when waiting on the condvar, the lockobj is released (this is done automatically and atomically by the way condition variables work). It's reacquired before the waiting thread regains execution, however.
Chris Jester-Young
See http://www.opengroup.org/onlinepubs/009695399/functions/pthread_cond_wait.html on the mutex-releasing behaviour.
Chris Jester-Young
Ah! You're right, thank you! This simplifies things.
Nicholas Mancuso
*nods* Also, remember to do the check using a while loop, not an if statement. There are rare occasions (called "spurious wakeups", in the link above on pthread_cond_wait) where your waiting thread gets woken up by, umm, outside circumstances.
Chris Jester-Young
As a side note, having finally looked at the source code of the windows implementation of pthreads. pthread_cond_t's are implemented with windows events!I have come full circle i guess!
Nicholas Mancuso
Ah hahaha! Well, I guess that goes to show either one can be implemented in terms of the other! :-)
Chris Jester-Young
A: 

Alternative answer (also in pseudocode) if you want multiple signallings (i.e., if signalled twice, then two threads can wait before the state is unsignalled again).

Waiting side:

lock(lockobj);
while (signalled != 0) {
    wait(condvar);
}
--signalled;
unlock(lockobj);

Signalling side:

lock(lockobj);
++signalled;
notify(condvar);
unlock(lockobj);
Chris Jester-Young
A: 

I ended up just wrapping a condition type in a new structure and created some simple functions to behave much like the EventWaitHandle from C#. I needed two mutexes to acheive proper serialized access.

The the cond_mutex is used for waiting on the conditional variable, while the data_mutex is used when setting the state from signaled to not signaled.

The reset mode is the same from C#. AUTO or MANUAL. This allows for the event_wait_t to reset itself automatically after waiting. Or letting the programmer manually do it with a call to event_wait_reset(event_wait_t *ewh);

Nicholas Mancuso
No, 1 mutex is enough for that. See my comment (about the mutex-releasing behaviour of pthread_cond_wait) about why this works. (event_wait_reset can use the same mutex.)
Chris Jester-Young