Motr  M0
Conditional variable.

Data Structures

struct  m0_cond
 

Functions

M0_INTERNAL void m0_cond_init (struct m0_cond *cond, struct m0_mutex *mutex)
 
M0_INTERNAL void m0_cond_fini (struct m0_cond *cond)
 
M0_INTERNAL void m0_cond_wait (struct m0_cond *cond)
 
M0_INTERNAL bool m0_cond_timedwait (struct m0_cond *cond, const m0_time_t abs_timeout)
 
M0_INTERNAL void m0_cond_signal (struct m0_cond *cond)
 
M0_INTERNAL void m0_cond_broadcast (struct m0_cond *cond)
 

Detailed Description

Condition variable is a widely known and convenient synchronization mechanism.

Notionally, a condition variable packages two things: a predicate ("a condition", hence the name) on computation state, e.g., "a free buffer is available", "an incoming request waits for processing" or "all worker threads have finished", and a mutex (m0_mutex) protecting changes to the state affecting the predicate.

There are two parts in using condition variable:

void buffer_put(struct m0_buffer *buf) {
// buffer is being returned to the pool...
m0_mutex_lock(&buffer_pool_lock);
// add the buffer to the free list
buf_tlist_add(&buffer_pool_free, buf);
// and signal the condition variable
m0_cond_signal(&buffer_pool_hasfree);
m0_mutex_unlock(&buffer_pool_lock);
}
struct m0_buffer *buffer_get(void) {
struct m0_buffer *buf;
m0_mutex_lock(&buffer_pool_lock);
while (buf_tlist_is_empty(&buffer_pool_free))
m0_cond_wait(&buffer_pool_hasfree);
buf = buf_tlist_head(&buffer_pool_free);
buf_tlist_del(buf);
m0_mutex_unlock(&buffer_pool_lock);
return buf;
}

Note that one has to re-check the predicate after m0_cond_wait() returns, because it might, generally, be false if multiple threads are waiting for predicate change (in the above example, if there are multiple concurrent calls to buffer_get()). This introduces one of the nicer features of condition variables: de-coupling of producers and consumers.

Condition variables are more reliable and structured synchronization primitive than channels (m0_chan), because the lock, protecting the predicate is part of the interface and locking state can be checked. On the other hand, channels can be used with predicates protected by read-write locks, atomic variables, etc.—where condition variables are not applicable.

See also
m0_chan
http://opengroup.org/onlinepubs/007908799/xsh/pthread_cond_wait.html
Todo:
Consider supporting other types of locks in addition to m0_mutex.

Very simple implementation of condition variables on top of waiting channels.

Self-explanatory.

See also
m0_chan

Function Documentation

◆ m0_cond_broadcast()

M0_INTERNAL void m0_cond_broadcast ( struct m0_cond cond)

Wakes up all threads waiting on the condition variable.

Precondition
m0_mutex_is_locked(mutex)

Definition at line 100 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ m0_cond_fini()

M0_INTERNAL void m0_cond_fini ( struct m0_cond cond)

Definition at line 46 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ m0_cond_init()

M0_INTERNAL void m0_cond_init ( struct m0_cond cond,
struct m0_mutex mutex 
)

Definition at line 40 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ m0_cond_signal()

M0_INTERNAL void m0_cond_signal ( struct m0_cond cond)

Wakes up no more than one thread waiting on the condition variable.

Precondition
m0_mutex_is_locked(mutex)

Definition at line 94 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ m0_cond_timedwait()

M0_INTERNAL bool m0_cond_timedwait ( struct m0_cond cond,
const m0_time_t  abs_timeout 
)

This is the same as m0_cond_wait, except that it has a timeout value. If the time expires before event is pending, this function will return false.

Note
Unlike pthread_cond_timedwait, m0_cond_timedwait can succeed if the event is immediately pending, even if the abs_timeout is in the past. If blocking occurs and abs_timeout is in the past, m0_cond_timedwait will return false. pthread_cond_timedwait always fails when abs_timeout is in the past.
Parameters
abs_timeoutthis is the time since Epoch (00:00:00, 1 January 1970).
Returns
true if condition is signaled before timeout.
false if condition variable is not signaled but timeout expires. errno is ETIMEDOUT;

Definition at line 74 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ m0_cond_wait()

M0_INTERNAL void m0_cond_wait ( struct m0_cond cond)

Atomically unlocks the mutex, waits on the condition variable and locks the mutex again before returning.

Precondition
m0_mutex_is_locked(mutex)
Postcondition
m0_mutex_is_locked(mutex)

Definition at line 52 of file cond.c.

Here is the call graph for this function:
Here is the caller graph for this function: