.. _condvar:

Condition Variables
###################

A :dfn:`condition variable` is a synchronization primitive
that enables threads to wait until a particular condition occurs.

.. contents::
    :local:
    :depth: 2

Concepts
********

Any number of condition variables can be defined (limited only by available RAM). Each
condition variable is referenced by its memory address.

To wait for a condition to become true, a thread can make use of a condition
variable.

A condition variable is basically a queue of threads that threads can put
themselves on when some state of execution (i.e., some condition) is not as
desired (by waiting on the condition). The function
:c:func:`k_condvar_wait` performs atomically the following steps;

#. Releases the last acquired mutex.
#. Puts the current thread in the condition variable queue.

Some other thread, when it changes said state, can then wake one (or more)
of those waiting threads and thus allow them to continue by signaling on
the condition using :c:func:`k_condvar_signal` or
:c:func:`k_condvar_broadcast` then it:

#. Re-acquires the mutex previously released.
#. Returns from :c:func:`k_condvar_wait`.

A condition variable must be initialized before it can be used.


Implementation
**************

Defining a Condition Variable
=============================

A condition variable is defined using a variable of type :c:struct:`k_condvar`.
It must then be initialized by calling :c:func:`k_condvar_init`.

The following code defines a condition variable:

.. code-block:: c

    struct k_condvar my_condvar;

    k_condvar_init(&my_condvar);

Alternatively, a condition variable can be defined and initialized at compile time
by calling :c:macro:`K_CONDVAR_DEFINE`.

The following code has the same effect as the code segment above.

.. code-block:: c

    K_CONDVAR_DEFINE(my_condvar);

Waiting on a Condition Variable
===============================

A thread can wait on a condition by calling :c:func:`k_condvar_wait`.

The following code waits on the condition variable.


.. code-block:: c

    K_MUTEX_DEFINE(mutex);
    K_CONDVAR_DEFINE(condvar)

    int main(void)
    {
        k_mutex_lock(&mutex, K_FOREVER);

        /* block this thread until another thread signals cond. While
         * blocked, the mutex is released, then re-acquired before this
         * thread is woken up and the call returns.
         */
        k_condvar_wait(&condvar, &mutex, K_FOREVER);
        ...
        k_mutex_unlock(&mutex);
    }

Signaling a Condition Variable
===============================

A condition variable is signaled on by calling :c:func:`k_condvar_signal` for
one thread or by calling :c:func:`k_condvar_broadcast` for multiple threads.

The following code builds on the example above.

.. code-block:: c

    void worker_thread(void)
    {
        k_mutex_lock(&mutex, K_FOREVER);

        /*
         * Do some work and fulfill the condition
         */
        ...
        ...
        k_condvar_signal(&condvar);
        k_mutex_unlock(&mutex);
    }

Suggested Uses
**************

Use condition variables with a mutex to signal changing states (conditions) from
one thread to another thread.
Condition variables are not the condition itself and they are not events.
The condition is contained in the surrounding programming logic.

Mutexes alone are not designed for use as a notification/synchronization
mechanism. They are meant to provide mutually exclusive access to a shared
resource only.

Configuration Options
*********************

Related configuration options:

* None.

API Reference
**************

.. doxygengroup:: condvar_apis
