[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference clt::cma

Title:DECthreads Conference
Moderator:PTHRED::MARYSTEON
Created:Mon May 14 1990
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:1553
Total number of notes:9541

1538.0. "How to implement NT Pulse function using Posix threads" by NNTPD::"[email protected]" (Knizhnik) Mon May 05 1997 10:46

I need to emulate functionality of Windows NT PulseEvent function
using Posix thread (i.e. i want to wakeup all waiting threads
and then reset event to non-signaled state). 
As far as pthread_cond_wait might return when condition
variable has not been signaled or broadcast (spurious wakeup)
it is necessary to enclose pthread_cond_wait in loop that
checks some predicate. But the problem is that PulseEvent
should reset the event, so predicate will be set to false before
waiting thread wakeup. So the following implementation doesn't work:

class event {
    pthread_cond_t  cond;
    pthread_mutex_t mutex;
    bool signaled;
    void signal() { 
        pthread_mutex_lock(&mutex);
        while (!signaled) { 
            pthread_cond_wait(&cond, &mutex);
        }   
        pthread_mutex_unlock(&mutex);
    }
    void pulse() { 
	signaled = true;
	pthread_cond_broadcast(&cond);
	signaled = false;		
    }
};
[Posted by WWW Notes gateway]
T.RTitleUserPersonal
Name
DateLines
1538.1use a counter?FLOYD::YODERIt's 999,943 to 1 but it just might workMon May 05 1997 13:3224
How about using a counter, n_signals, of the number of times 'pulse' has been
called?  (It must be made large enough to not overflow: 128 bits ought to always
suffice, for example.)  Then the implementation would be something like:

class event {
    pthread_cond_t  cond;
    pthread_mutex_t mutex;
    long n_signals = 0; /* Can be made a pair of longs */
    void signal() {
        long old_n_signals;
        pthread_mutex_lock(&mutex);
        old_n_signals = n_signals;
        while (n_signals == old_n_signals) { 
            pthread_cond_wait(&cond, &mutex);
        }   
        pthread_mutex_unlock(&mutex);
    }
    void pulse() {
        pthread_mutex_lock(&mutex);
	n_signals++;
        pthread_mutex_unlock(&mutex);
	pthread_cond_broadcast(&cond);
    }
};
1538.2Mike's idea is fine; but be sure to use a mutex!WTFN::SCALESDespair is appropriate and inevitable.Mon May 05 1997 15:4324
Re .0:  When you set the predicate and/or broadcast the condition variable you
absolutely MUST do so under a mutex.  Otherwise, your code may not function
reliably.


Re .1, Mike's idea looks fine to me.  (The alternative is to maintain a list of
waiters, have each waiter use a separate predicate, have the waker set each
predicate, and then wake each waiter either by broadcasting on a common
condition variable or by signalling each thread waiting on its own CV...)

.1> It must be made large enough to not overflow

I don't see any reason why this would be true.  The code works just fine if the
counter wraps, just so long as the counter doesn't manage to wrap all the way
around to the previous value at the moment the waiter manages to wake up and
check (and, with at least 16 bits I'd say you're pretty safe, the more the safer
obviously).

.1> 128 bits ought to always suffice, for example.

"Always"...until the processors get "really fast"...  ;-)


				Webb
1538.3Add a cancellation handler.WTFN::SCALESDespair is appropriate and inevitable.Mon May 05 1997 15:457
Oh, and one other thing:  condition waits are cancellation points, so if you
want your code to be "cancel-safe" (and you should want this, if you're
providing an API), you'll need to use an exception handler or a cancellation
handler to unlock the mutex in the event of a cancellation.


				Webb