logo
Free, unlimited AI code reviews that run on commit
git-lrc git-lrc GitHub Install Now We'd appreciate a star git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt git-lrc - Free, unlimited AI code reviews that run on commit | Product Hunt

Condition - Condition variables.

Documentation

       Module Condition
        : sigend

       Condition variables.

       Condition  variables  are  useful  when  several  threads  wish to access a shared data structure that is
       protected by a mutex (a mutual exclusion lock).

       A condition variable is a communication channel. On the receiver side, one or more threads  can  indicate
       that  they  wish  to  wait for a certain property to become true. On the sender side, a thread can signal
       that this property has become true, causing one (or more) waiting threads to be woken up.

       For instance, in the implementation of a queue data structure, if a thread  that  wishes  to  extract  an
       element finds that the queue is currently empty, then this thread waits for the queue to become nonempty.
       A  thread  that inserts an element into the queue signals that the queue has become nonempty. A condition
       variable is used for this purpose. This communication channel conveys the information that  the  property
       "the queue is nonempty" is true, or more accurately, may be true. (We explain below why the receiver of a
       signal cannot be certain that the property holds.)

       To continue the example of the queue, assuming that the queue has a fixed maximum capacity, then a thread
       that  wishes  to  insert  an element may find that the queue is full. Then, this thread must wait for the
       queue to become not full, and a thread that extracts an element of the queue signals that the  queue  has
       become not full. Another condition variable is used for this purpose.

       In  short,  a  condition  variable  c is used to convey the information that a certain property P about a
       shared data structure D, protected by a mutex m , may be true.

       Condition variables provide an efficient alternative to busy-waiting.  When one wishes to  wait  for  the
       property P to be true, instead of writing a busy-waiting loop:
            Mutex.lockm;whilenotPdoMutex.unlockm;Mutex.lockmdone;<updatethedatastructure>;Mutex.unlockm

       one uses Condition.wait in the body of the loop, as follows:
            Mutex.lockm;whilenotPdoCondition.waitcmdone;<updatethedatastructure>;Mutex.unlockm

       The  busy-waiting  loop  is  inefficient  because the waiting thread consumes processing time and creates
       contention of the mutex m .  Calling Condition.wait allows the waiting thread to be suspended, so it does
       not consume any computing resources while waiting.

       With a condition variable c , exactly one mutex m is associated.  This association is implicit: the mutex
       m is not explicitly passed as an argument to Condition.create . It is up to the programmer to  know,  for
       each condition variable c , which is the associated mutex m .

       With a mutex m , several condition variables can be associated.  In the example of the bounded queue, one
       condition variable is used to indicate that the queue is nonempty, and another condition variable is used
       to indicate that the queue is not full.

       With  a  condition  variable  c  ,  exactly one logical property P should be associated. Examples of such
       properties include "the queue is nonempty" and "the queue is not full".  It is up to  the  programmer  to
       keep  track,  for  each  condition  variable,  of  the corresponding property P.  A signal is sent on the
       condition variable c as an indication that the property P is true, or may be true.  On the receiving end,
       however, a thread that is woken up cannot  assume  that  P  is  true;  after  a  call  to  Condition.wait
       terminates,  one  must explicitly test whether P is true.  There are several reasons why this is so.  One
       reason is that, between the moment when the signal is sent and the moment when a waiting thread  receives
       the signal and is scheduled, the property P may be falsified by some other thread that is able to acquire
       the mutex m and alter the data structure D.  Another reason is that spurious wakeups may occur: a waiting
       thread can be woken up even if no signal was sent.

       Here  is  a  complete example, where a mutex protects a sequential unbounded queue, and where a condition
       variable is used to signal that the queue is nonempty.
            type'asafe_queue={queue:'aQueue.t;mutex:Mutex.t;nonempty:Condition.t}letcreate()={queue=Queue.create();mutex=Mutex.create();nonempty=Condition.create()}letaddvq=Mutex.lockq.mutex;letwas_empty=Queue.is_emptyq.queueinQueue.addvq.queue;ifwas_emptythenCondition.broadcastq.nonempty;Mutex.unlockq.mutexlettakeq=Mutex.lockq.mutex;whileQueue.is_emptyq.queuedoCondition.waitq.nonemptyq.mutexdone;letv=Queue.takeq.queuein(*cannotfailsincequeueisnonempty*)Mutex.unlockq.mutex;v

       Because the call to Condition.broadcast takes place inside the critical section, the  following  property
       holds  whenever  the mutex is unlocked: if the queue is nonempty, then no thread is waiting, or, in other
       words, if some thread is waiting, then the queue must be empty.  This  is  a  desirable  property:  if  a
       thread  that  attempts  to  execute  a  take  operation  could  remain suspended even though the queue is
       nonempty, that would be a problematic situation, known as a deadlock.

       typet

       The type of condition variables.

       valcreate : unit->tcreate() creates and returns a new condition variable.  This condition variable should be associated  (in
       the programmer's mind) with a certain mutex m and with a certain property P of the data structure that is
       protected by the mutex m .

       valwait : t->Mutex.t->unit

       The call waitcm is permitted only if m is the mutex associated with the condition variable c , and only
       if  m  is  currently locked.  This call atomically unlocks the mutex m and suspends the current thread on
       the condition variable c . This thread can later be woken up after the  condition  variable  c  has  been
       signaled  via  Condition.signal  or Condition.broadcast ; however, it can also be woken up for no reason.
       The mutex m is locked again before wait returns. One cannot assume that the property  P  associated  with
       the  condition variable c holds when wait returns; one must explicitly test whether P holds after calling
       wait .

       valsignal : t->unitsignalc wakes up one of the threads waiting on the condition variable c , if there is one. If  there  is
       none, this call has no effect.

       It  is recommended to call signalc inside a critical section, that is, while the mutex m associated with
       c is locked.

       valbroadcast : t->unitbroadcastc wakes up all threads waiting on the condition variable c . If there are none, this  call  has
       no effect.

       It  is  recommended  to call broadcastc inside a critical section, that is, while the mutex m associated
       with c is locked.

OCamldoc                                           2025-06-12                                      Condition(3o)

Module

       Module   Condition

Name

       Condition - Condition variables.

See Also