1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 <2016> 2017 2018 2019 2020 2021 2022 2023 2024 | Index | 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 <2016> 2017 2018 2019 2020 2021 2022 2023 2024 |
<== Date ==> | <== Thread ==> |
---|
Subject: | Re: epicsEventSignal() question |
From: | Till Straumann <[email protected]> |
To: | Michael Westfall <[email protected]>, Andrew Johnson <[email protected]> |
Cc: | [email protected] |
Date: | Mon, 6 Jun 2016 18:41:48 -0700 |
On 06/06/2016 05:14 PM, Michael
Westfall wrote:
That's probably not that easy. You'd have to increment that counter and block for an event atomically. This is exactly what a posix condition variable does. The posix implementation uses this mechanism for the epicsEvent implementation (and pthread_cond_broadcast could be used naturally). In any case you'll have to be careful: a semaphore has defined semantics (counts the number of available resources) these no longer hold in a 'broadcast' scenario (how many resources will become available as a result of a broadcast?). In a situation where you'd want to broadcast an 'event' or 'condition' reflects the semantics better than a semaphore: assume you have a number of threads which you want to synchronize with a condition: You can have multiple threads waiting for a condition: /* step 1 */ pthread_mutex_lock( &mtx ); while ( ! event_has_happened ) { pthread_cond_wait( &cond, &mtx ); /* step 2a, 2b */ } pthread_mutex_unlock( &mtx ); /* step 3 */ The sender signals the event: pthread_mutex_lock( &mtx ); event_has_happened = 1; pthread_cond_broadcast( &cond ); pthread_mutex_unlock( &mtx ); With the above synchronization it is ensured that all receiving threads get to step 3. No matter if they were at step 1 (not testing event yet) or step 2 past testing 'event_has_happened' and not yet asleep (2a) or past testing and already asleep (2b) when the sender signalled the event. With your counter approach (assuming you atomically increment/decrement the counter) receiver: waiting++ epicsEventWait(); sender: while ( waiting-- ) epicsEventSend() You generate several race conditions: - any number of receivers that have not yet incremented the counter when the sender signals is never woken up. - unless the underlying semaphore is a counting semaphore there may be less threads woken up than 'waiting' counted (if e.g., two threads have incremented 'waiting' but are not yet asleep and epicsEventSend is executed twice then one event is lost). You *can* implement an event broadcast with elementary epics devices (epicsEvent, epicsMutex) but you have to be very careful. Any textbook discusses the implementation of one kind of device by using others. HTH - Till
|