Abhishek Jain
Abhishek Jain

Reputation: 10582

Event on Windows and Mutex/Condition Variable on Posix used for implementing wait able events, what if no thread is blocked?

In case of Events on Windows, If no threads are waiting, the event object's state remains signaled. What happens in case of pthread_cond_signal, what happens in case if no threads are blocked?

Upvotes: 1

Views: 999

Answers (2)

GermanDev
GermanDev

Reputation: 23

Some people state to use IPC (InterProcess Communication) semaphores to 'emulate' the behaviour of MS Windows (Windows events compared to POSIX condition variables).

The problem with IPC semaphores is their 'global management' in your UNIX box, i.e. a process using semaphores that get killed by a SIGKILL signal will leave allocated semaphores allocated until the next reboot (or until someone actively removes them) - you may even run out of sempaphores, which is really bad.

POSIX thread, mutexes, and condition variables are for INTRAprocess communication (not INTER). My solution uses an atomic counter in addition to the pair of (MUTEX,CONDVAR) to fix the problem of 'forgotten' signals if noone is currently waiting for it (no error handling here):

pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t event_condvar = PTHREAD_COND_INITIALIZER;
volatile long event_counter = 0L;
(...)
/* how to signal: */
    pthread_mutex_lock(&event_mutex);
    __sync_fetch_and_add(&event_counter,1);
    pthread_cond_signal(&event_condvar);
    pthread_mutex_unlock(&event_mutex);
(...)
/* how to wait: */
if (__sync_fetch_and_and(&signalled, -1) > 0) /* optional fast path, no mutex lock */
{
  __sync_fetch_and_sub(&signalled, 1);
  return;
}
pthread_mutex_lock(&event_mutex);
if (__sync_fetch_and_and(&signalled, -1) > 0) /* check again, there might be happened something in between */
{
  __sync_fetch_and_sub(&signalled, 1);
  pthread_mutex_unlock(&event_mutex);
  return;
}
pthread_cond_wait(&event_condvar, &event_mutex); /* implicitly unlocks mutex while waiting */
__sync_fetch_and_sub(&signalled, 1);
pthread_mutex_unlock(&event_mutex);

The first checking of the atomic variable is kind of a 'fast path' without locking the mutex first (still synchronized across CPUs, CPU cores, etc.).

This is a very simple example, which could be modified by adding pthread_cond_timedwait. Furthermore, if you want to fully reset the event, substitute all occurrences of '__sync_fetch_and_sub(&signalled, 1)' by '__sync_fetch_and_and(&signalled, 0)'.

This just implements the Windows event behaviour for the 'producer-consumer pattern' i.e. one thread (producer) has to signal something to ONE other thread (consumer) waiting for this event.

Upvotes: 0

user3793679
user3793679

Reputation:

For pthread_cond_signal()... if there are no threads waiting at that exact moment, nothing happens, nothing at all -- in particular, the signal is completely forgotten, it is as if it had never happened.

IMHO POSIX "condition variables" are badly named, because the name suggests that the "condition variable" has a value, and it is natural to suppose that the value might collect pending signals. Nothing could be further from the truth. (For that you need "semaphores".)

The "state" associated with the "condition" is what matters. A thread which needs to wait for the "state" to have a particular value will:

  pthread_mutex_lock(foo_mutex) ;

  while (...state not as required...)
    pthread_cond_wait(foo_cond, foo_mutex) ;

  ...perhaps update the state...

  pthread_mutex_unlock(foo_mutex) ;

A thread which updates the "state" such that some other thread may now continue, will:

  pthread_mutex_lock(foo_mutex) ;

  ...update the state...

  if (...there may be a waiter...)
    pthread_cond_signal(foo_cond) ;

  pthread_mutex_unlock(foo_mutex) ;

NB: the standard explicitly allows pthread_cond_signal() to start one, some or all waiters... hence the while(...) loop in the waiter... and the waiter that "claims" the signal needs to update the state so that any other threads will loop in that while (...)

Upvotes: 3

Related Questions