[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