Implementing Windows Event on Linux using conditional variables?

I am trying to implement very simple Windows events on Linux. Only for my scenario - 3 threads, 1 primary and 2 secondary. Each of the secondary threads raises 1 event by SetEvent, and the main thread expects it. Example:

int main() { void* Events[2]; Events[0] = CreateEvent(); Events[1] = CreateEvent(); pthread_start(Thread, Events[0]); pthread_start(Thread, Events[1]); WaitForMultipleObjects(2, Events, 30000) // 30 seconds timeout return 0; } int* thread(void* Event) { // Do something SetEvent(Event); // Do something } 

So, to implement it, I use conditional variables. But my question is the right way? Or am I doing something wrong? My implementation:

 // Actually, this function return pointer to struct with mutex and cond // here i just simplified example void* CreateEvent(mutex, condition) { pthread_mutex_init(mutex, NULL); pthread_cond_init(condition, NULL); } bool SetEvent (mutex, condition) { pthread_mutex_lock(mutex); pthread_cond_signal(condition); pthread_mutex_unlock(mutex); } int WaitForSingleObject(mutex, condition, timeout) { pthread_mutex_lock(mutex); pthread_cond_timedwait(condition, mutex, timeout); pthread_mutex_unlock(mutex); } // Call WaitForSingleObject for each event. // Yes, i know, that its a wrong way, but it should work in my example. int WaitForMultipleObjects(count, mutex[], condition[], timeout); 

And everything seems good, but I think this problem will appear when I call the WaitFor .. function in the main thread before SetEvent is called in the secondary thread. On Windows, this worked well, but on Linux - only the idea is described above.

Maybe you can tell me how best to solve this? Thanks.

UPD: The timeout is very important because one of the secondary threads cannot pass SetEvent ().

+7
source share
3 answers

There was already a similar stackoverflow question: the equivalent of WaitForSingleObject and WaitForMultipleObjects on Linux

Alternatively, you can use semaphores:

 sem_t semOne ; sem_t semTwo ; sem_t semMain ; 

In the main thread:

 sem_init(semOne,0,0) ; sem_init(semTwo,0,0) ; sem_init(semMain,0,0) ; ... sem_wait(&semMain); // Thread 1 sem_wait(&semOne); sem_post(&semMain); // Thread 2 sem_wait(&semTwo); sem_post(&semMain); 

A detailed description and various examples can be found here: http://www.ibm.com/developerworks/linux/library/l-ipc2lin3/index.html

+1
source

Based on description of WaitForSingleObject

The WaitForSingleObject function checks the current state of the specified object. If the state of the object does not matter, the calling thread transitions to the idle state until the object is signaled or the timeout period expires.

The difference between this behavior and the code is that the code will always expect a condition variable since it does not check the predicate. This leads to synchronization problems between calls to pthread_condt_timewait and pthread_cond_signal .

Common idiom for signaling a condition variable:

  lock mutex
 set predicate
 unlock mutex
 signal condition variable

And while waiting for the condition variable:

  lock mutex
 while (! predicate)
 { 
   wait on condition variable
 }
 unlock mutex 

Depending on what is trying to be achieved, a separate bool can be used as a predicate for each Event . Having entered the predicate, WaitForSingleObject should wait only for the condition variable if the Event not been signaled. The code will look something like this:

 bool SetEvent (mutex, condition) { pthread_mutex_lock(mutex); // lock mutex bool& signalled = find_signal(condition); // find predicate signalled = true; // set predicate pthread_mutex_unlock(mutex); // unlock mutex pthread_cond_signal(condition); // signal condition variable } int WaitForSingleObject(mutex, condition, timeout) { pthread_mutex_lock(mutex); // lock mutex bool& signalled = find_signal(condition); // find predicate while (!signalled) { pthread_cond_timedwait(condition, mutex, timeout); } signalled = false; // reset predicate pthread_mutex_unlock(mutex); // unlock mutex } 
+3
source

I think semaphore is the best solution here because it can be used for interprocess communication. You can wrap the interface if no name is specified, then use pthread_ to initialize it for use within the process, which may reduce resource usage, but when using the name, try to use it to initialize for use inside the process.

0
source

All Articles