Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

ConditionVariable Class Reference

The ConditionVariable class is a synchronization primitive that allows threads to wait until a particular condition occurs. More...

#include <ConditionVariable.h>

Inherits NonCopyable< ConditionVariable >.

Public Member Functions

 ConditionVariable (Mutex &mutex)
 Create and initialize a ConditionVariable object.
void wait ()
 Wait for a notification.
bool wait_until (uint64_t millisec)
 Wait for a notification until the specified time.
bool wait_for (uint32_t millisec)
 Wait for a notification or timeout.
void notify_one ()
 Notify one waiter on this condition variable that a condition changed.
void notify_all ()
 Notify all waiters on this condition variable that a condition changed.
 ~ConditionVariable ()
 ConditionVariable destructor.

Private Member Functions

 MBED_DEPRECATED ("Invalid copy construction of a NonCopyable resource.") NonCopyable(const NonCopyable &)
 NonCopyable copy constructor.
 MBED_DEPRECATED ("Invalid copy assignment of a NonCopyable resource.") NonCopyable &operator
 NonCopyable copy assignment operator.

Detailed Description

The ConditionVariable class is a synchronization primitive that allows threads to wait until a particular condition occurs.

Use the condition variable in conjunction with a mutex to safely wait for or notify waiters of condition changes to a resource accessible by multiple threads.

The thread that intends to wait on a ConditionVariable must:

  • Acquire a lock on a mutex.
  • Execute `wait`, `wait_for` or `wait_until`. While the thread is waiting, the mutex is unlocked.
  • When the condition variable has been notified, or in the case of `wait_for` and `wait_until` the timeout expires, the thread is awakened.

The thread that intends to notify a ConditionVariable must:

  • Acquire a lock on the mutex used to construct the condition variable.
  • Execute `notify_one` or `notify_all` on the condition variable.

All threads waiting on the condition variable wake when `ConditionVariablenotify_all` is called. At least one thread waiting on the condition variable wakes when `ConditionVariablenotify_one` is called.

While a thread is waiting for notification of a ConditionVariable, it releases the lock held on the mutex. The ConditionVariable reacquires the mutex lock before exiting the wait function.

#### Unspecified behavior

  • The thread that is unblocked on `ConditionVariablenotify_one` is unspecified if there are multiple waiters.
  • When `ConditionVariablenotify_one` or `ConditionVariablenotify_all` is called and there are one or more waiters, and one or more threads attempting to acquire the condition variable's mutex, the order in which the mutex is acquired is unspecified.
  • Spurious notifications (not triggered by the application) can occur.

#### Undefined behavior

  • Calling wait if the mutex is not locked by the current thread is undefined behavior.
  • The order in which waiting threads acquire the condition variable's mutex after `ConditionVariablenotify_all` is called is undefined.
  • The behavior of `ConditionVariablewait` and `ConditionVariablewait_for` is undefined if the condition variable's mutex is locked more than once by the calling thread.
Note:
Synchronization level: Thread safe

Example:

 #include "mbed.h"

 Mutex mutex;
 ConditionVariable cv(mutex);

 // These variables are protected by locking the mutex.
 uint32_t work_count = 0;
 bool done = false;

 void worker_thread()
 {
   // Acquire lock on mutex before accessing protected variables and waiting.
   mutex.lock();

   while (done == false) {
     printf("Worker thread: Count: %lu\r\n", work_count);

     // Wait for main thread to notify the condition variable.
     printf("Worker thread: Waiting\r\n");
     cv.wait();
   }

   printf("Worker: Exiting\r\n");

   // The condition variable acquires the lock when exiting the `wait` function.
   // Unlock mutex when exiting the thread.
   mutex.unlock();
 }

 int main()
 {
   Thread thread;
   thread.start(worker_thread);

   for (int i = 0; i < 5; i++) {
     // Acquire lock on mutex before modifying variables and notifying.
     mutex.lock();

     // Change count and notify waiters.
     work_count++;
     printf("Main thread: Set count to: %lu\r\n", work_count);
     printf("Main thread: Notifying worker thread\r\n");
     cv.notify_all();

     // Mutex must be unlocked before the worker thread can acquire it.
     mutex.unlock();

     wait(1.0);
   }

   // Change done and notify waiters of this.
   mutex.lock();
   done = true;
   cv.notify_all();
   mutex.unlock();

   thread.join();

   printf("Main: Exiting\r\n");
 }

Definition at line 158 of file ConditionVariable.h.


Constructor & Destructor Documentation

ConditionVariable ( Mutex mutex )

Create and initialize a ConditionVariable object.

Note:
You cannot call this function from ISR context.

Definition at line 38 of file ConditionVariable.cpp.

ConditionVariable destructor.

Note:
You cannot call this function from ISR context.

Definition at line 149 of file ConditionVariable.cpp.


Member Function Documentation

void notify_all (  )

Notify all waiters on this condition variable that a condition changed.

This function unblocks all of the threads waiting for the condition variable.

Note:
- The thread calling this function must be the owner of the ConditionVariable's mutex.
- If there are one or more waiters and one or more threads attempting to acquire the condition variable's mutex the order in which the mutex is acquired is undefined.
You cannot call this function from ISR context.

Definition at line 95 of file ConditionVariable.cpp.

void notify_one (  )

Notify one waiter on this condition variable that a condition changed.

This function unblocks one of the threads waiting for the condition variable.

Note:
- The thread calling this function must be the owner of the ConditionVariable's mutex.
- The thread that is unblocked on ConditionVariable::notify_one is undefined if there are multiple waiters.
You cannot call this function from ISR context.

Definition at line 86 of file ConditionVariable.cpp.

void wait (  )

Wait for a notification.

Wait causes the current thread to block until the condition variable receives a notification from another thread.

Note:
- The thread calling this function must be the owner of the ConditionVariable's mutex, and it must be locked exactly once.
- Spurious notifications can occur, so the caller of this API should check to make sure the condition the caller is waiting on has been met.
- The current thread releases the lock while inside the wait function and reacquires it upon exiting the function.

Example:

 mutex.lock();

 while (!condition_met) {
     cond.wait();
 }

 function_to_handle_condition();

 mutex.unlock();
Note:
You cannot call this function from ISR context.

Definition at line 43 of file ConditionVariable.cpp.

bool wait_for ( uint32_t  millisec )

Wait for a notification or timeout.

`Wait for` causes the current thread to block until the condition variable receives a notification from another thread, or the timeout specified by the millisec parameter is reached.

Parameters:
millisecTimeout value or osWaitForever in case of no timeout.
Returns:
`true` if a timeout occurred, `false` otherwise.
Note:
- The thread calling this function must be the owner of the ConditionVariable's mutex, and it must be locked exactly once.
- Spurious notifications can occur, so the caller of this API should check to make sure the condition the caller is waiting on has been met.
- The current thread releases the lock while inside the wait function and reacquire it upon exiting the function.

Example:

 mutex.lock();

 while (!condition_met) {
     cond.wait_for(MAX_SLEEP_TIME);
     if (!condition_met) {
         do_other_work_while_condition_false();
     }
 }

 if (condition_met) {
     function_to_handle_condition();
 }

 mutex.unlock();
Note:
You cannot call this function from ISR context.

Definition at line 48 of file ConditionVariable.cpp.

bool wait_until ( uint64_t  millisec )

Wait for a notification until the specified time.

Wait until causes the current thread to block until the condition variable is notified, or a specific time given by millisec parameter is reached.

Parameters:
millisecAbsolute end time referenced to `Kernelget_ms_count()`
Returns:
`true` if a timeout occurred, `false` otherwise.
Note:
- The thread calling this function must be the owner of the ConditionVariable's mutex, and it must be locked exactly once.
- Spurious notifications can occur, so the caller of this API should check to make sure the condition the caller is waiting on has been met.
- The current thread releases the lock while inside the wait function and reacquires it upon exiting the function.

Example:

 mutex.lock();
 uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;

 while (!condition_met) {
     if (cond.wait_until(end_time)) {
         break;
     }
 }

 if (condition_met) {
     function_to_handle_condition();
 }

 mutex.unlock();
Note:
You cannot call this function from ISR context.

Definition at line 68 of file ConditionVariable.cpp.