[vlc-devel] Clarifications on condition variables

Rémi Denis-Courmont remi at remlab.net
Sat Feb 6 18:40:27 CET 2010


	Hello,

Several people seem a bit confused regarding the use of thread condition 
variables. A condition variable is essentially a method to put threads to 
sleep and to wake them up.

A condition variable must *always* be associated with an external predicate. 
That's just a fancy name for a boolean expression. The predicate may be as 
complicated as needed, so long as it eventually evaluates to a boolean value. 
In trivial terms, the predicate is the 'Does this thread have something to 
do?' question.

A condition variable is used when a thread needs to wait for a predicate to 
become true. It is implicitly expected that *another* thread will change the 
state of the program such that the predicate becomes true. The predicate hence 
would depend on some shared state between two or more threads, typically one 
or a few variables in memory. Access to the shared sate must be synchronized 
since it involves more than one thread. That is why a condition variable is 
*always* combined with a mutual exclusion lock. When a thread needs to change 
or read the state, it must hold the lock.

There are many ways to use condition variables, but the most typical pattern 
is:

/* Thread that waits */
lock(mutex);
/* do something with the shared state */
while (!predicate)
    wait(condition, mutex);
/* do something */
unlock(mutex);


/* Thread that wakes up the other one */
lock(mutex);
/* do something */
if (predicate) // <-- this may be implicit if we know it is always true
    signal(condition);
unlock(mutex);

libvlc_InternalWait() and libvlc_Quit() are very simple examples. Here the 
predicate would be '!vlc_object_alive(p_libvlc)':

void libvlc_InternalWait( libvlc_int_t *p_libvlc )
{
    vlc_mutex_lock( &exit_lock );
    while( vlc_object_alive( p_libvlc ) )
        vlc_cond_wait( &exiting, &exit_lock );
    vlc_mutex_unlock( &exit_lock );
}

void libvlc_Quit( libvlc_int_t *p_libvlc )
{
    vlc_mutex_lock( &exit_lock );
    vlc_object_kill( p_libvlc );
    vlc_cond_broadcast( &exiting );
    vlc_mutex_unlock( &exit_lock );
}


Note that it really makes no sense to have a condition variable with no 
predicate. If the predicate were always true, then the thread would never 
wait/sleep, so it should call 'sched_yield()' instead or just busy loop. 
Conversely, if the predicate were always false, then the thread would always 
wait/sleep, so it should instead call 'msleep()' for a relative timer, 
'mwait()' for an absolute timer, or just 'for (;;) pause()' in the degenerate 
case.

Signal or broadcast? You use signal if you know that no more than one thread 
needs to wake up. In particular, you use signal if it is known that only one 
thread ever waits on the condition variable. Otherwise, the condition variable 
must be broadcasted - but this is less efficient.

-- 
Rémi Denis-Courmont
http://www.remlab.net/
http://fi.linkedin.com/in/remidenis



More information about the vlc-devel mailing list