Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
ConditionVariable.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2017-2017 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 #ifndef CONDITIONVARIABLE_H 00023 #define CONDITIONVARIABLE_H 00024 00025 #include <stdint.h> 00026 #include "cmsis_os.h" 00027 #include "rtos/Mutex.h" 00028 #include "rtos/Semaphore.h" 00029 00030 #include "platform/NonCopyable.h" 00031 00032 namespace rtos { 00033 /** \addtogroup rtos */ 00034 /** @{*/ 00035 00036 struct Waiter; 00037 00038 /** This class provides a safe way to wait for or send notifications of condition changes 00039 * 00040 * This class is used in conjunction with a mutex to safely wait for or 00041 * notify waiters of condition changes to a resource accessible by multiple 00042 * threads. 00043 * 00044 * # Defined behavior 00045 * - All threads waiting on the condition variable wake when 00046 * ConditionVariable::notify_all is called. 00047 * - If one or more threads are waiting on the condition variable at least 00048 * one of them wakes when ConditionVariable::notify is called. 00049 * 00050 * # Undefined behavior 00051 * - The thread which is unblocked on ConditionVariable::notify_one is 00052 * undefined if there are multiple waiters. 00053 * - The order which in which waiting threads acquire the condition variable's 00054 * mutex after ConditionVariable::notify_all is called is undefined. 00055 * - When ConditionVariable::notify_one or ConditionVariable::notify_all is 00056 * called and there are one or more waiters and one or more threads attempting 00057 * to acquire the condition variable's mutex the order in which the mutex is 00058 * acquired is undefined. 00059 * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for 00060 * is undefined if the condition variable's mutex is locked more than once by 00061 * the calling thread. 00062 * - Spurious notifications (not triggered by the application) can occur 00063 * and it is not defined when these occur. 00064 * 00065 * @note Synchronization level: Thread safe 00066 * 00067 * Example: 00068 * @code 00069 * #include "mbed.h" 00070 * 00071 * Mutex mutex; 00072 * ConditionVariable cond(mutex); 00073 * 00074 * // These variables are protected by locking mutex 00075 * uint32_t count = 0; 00076 * bool done = false; 00077 * 00078 * void worker_thread() 00079 * { 00080 * mutex.lock(); 00081 * do { 00082 * printf("Worker: Count %lu\r\n", count); 00083 * 00084 * // Wait for a condition to change 00085 * cond.wait(); 00086 * 00087 * } while (!done); 00088 * printf("Worker: Exiting\r\n"); 00089 * mutex.unlock(); 00090 * } 00091 * 00092 * int main() { 00093 * Thread thread; 00094 * thread.start(worker_thread); 00095 * 00096 * for (int i = 0; i < 5; i++) { 00097 * 00098 * mutex.lock(); 00099 * // Change count and notify waiters of this 00100 * count++; 00101 * printf("Main: Set count to %lu\r\n", count); 00102 * cond.notify_all(); 00103 * mutex.unlock(); 00104 * 00105 * wait(1.0); 00106 * } 00107 * 00108 * mutex.lock(); 00109 * // Change done and notify waiters of this 00110 * done = true; 00111 * printf("Main: Set done\r\n"); 00112 * cond.notify_all(); 00113 * mutex.unlock(); 00114 * 00115 * thread.join(); 00116 * } 00117 * @endcode 00118 */ 00119 class ConditionVariable : private mbed::NonCopyable<ConditionVariable> { 00120 public: 00121 /** Create and Initialize a ConditionVariable object */ 00122 ConditionVariable(Mutex &mutex); 00123 00124 /** Wait for a notification 00125 * 00126 * Wait until a notification occurs. 00127 * 00128 * @note - The thread calling this function must be the owner of the 00129 * ConditionVariable's mutex and it must be locked exactly once 00130 * @note - Spurious notifications can occur so the caller of this API 00131 * should check to make sure the condition they are waiting on has 00132 * been met 00133 * 00134 * Example: 00135 * @code 00136 * mutex.lock(); 00137 * while (!condition_met) { 00138 * cond.wait(); 00139 * } 00140 * 00141 * function_to_handle_condition(); 00142 * 00143 * mutex.unlock(); 00144 * @endcode 00145 */ 00146 void wait(); 00147 00148 /** Wait for a notification or timeout 00149 * 00150 * @param millisec timeout value or osWaitForever in case of no time-out. 00151 * @return true if a timeout occurred, false otherwise. 00152 * 00153 * @note - The thread calling this function must be the owner of the 00154 * ConditionVariable's mutex and it must be locked exactly once 00155 * @note - Spurious notifications can occur so the caller of this API 00156 * should check to make sure the condition they are waiting on has 00157 * been met 00158 * 00159 * Example: 00160 * @code 00161 * mutex.lock(); 00162 * Timer timer; 00163 * timer.start(); 00164 * 00165 * bool timed_out = false; 00166 * uint32_t time_left = TIMEOUT; 00167 * while (!condition_met && !timed_out) { 00168 * timed_out = cond.wait_for(time_left); 00169 * uint32_t elapsed = timer.read_ms(); 00170 * time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed; 00171 * } 00172 * 00173 * if (condition_met) { 00174 * function_to_handle_condition(); 00175 * } 00176 * 00177 * mutex.unlock(); 00178 * @endcode 00179 */ 00180 bool wait_for(uint32_t millisec); 00181 00182 /** Notify one waiter on this condition variable that a condition changed. 00183 * 00184 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex 00185 */ 00186 void notify_one(); 00187 00188 /** Notify all waiters on this condition variable that a condition changed. 00189 * 00190 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex 00191 */ 00192 void notify_all(); 00193 00194 ~ConditionVariable(); 00195 00196 protected: 00197 struct Waiter { 00198 Waiter(); 00199 Semaphore sem; 00200 Waiter *prev; 00201 Waiter *next; 00202 bool in_list; 00203 }; 00204 00205 static void _add_wait_list(Waiter **wait_list, Waiter *waiter); 00206 static void _remove_wait_list(Waiter **wait_list, Waiter *waiter); 00207 Mutex &_mutex; 00208 Waiter *_wait_list; 00209 }; 00210 00211 } 00212 #endif 00213 00214 /** @}*/
Generated on Thu Jul 14 2022 14:36:14 by
