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 * 00123 * @note You cannot call this function from ISR context. 00124 */ 00125 ConditionVariable(Mutex &mutex); 00126 00127 /** Wait for a notification 00128 * 00129 * Wait until a notification occurs. 00130 * 00131 * @note - The thread calling this function must be the owner of the 00132 * ConditionVariable's mutex and it must be locked exactly once 00133 * @note - Spurious notifications can occur so the caller of this API 00134 * should check to make sure the condition they are waiting on has 00135 * been met 00136 * 00137 * Example: 00138 * @code 00139 * mutex.lock(); 00140 * while (!condition_met) { 00141 * cond.wait(); 00142 * } 00143 * 00144 * function_to_handle_condition(); 00145 * 00146 * mutex.unlock(); 00147 * @endcode 00148 * 00149 * @note You cannot call this function from ISR context. 00150 */ 00151 void wait(); 00152 00153 /** Wait for a notification until specified time 00154 * 00155 * @param millisec absolute end time referenced to Kernel::get_ms_count() 00156 * @return true if a timeout occurred, false otherwise. 00157 * 00158 * @note - The thread calling this function must be the owner of the 00159 * ConditionVariable's mutex and it must be locked exactly once 00160 * @note - Spurious notifications can occur so the caller of this API 00161 * should check to make sure the condition they are waiting on has 00162 * been met 00163 * 00164 * Example: 00165 * @code 00166 * mutex.lock(); 00167 * uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT; 00168 * 00169 * while (!condition_met) { 00170 * if (cond.wait_until(end_time)) { 00171 * break; 00172 * } 00173 * } 00174 * 00175 * if (condition_met) { 00176 * function_to_handle_condition(); 00177 * } 00178 * 00179 * mutex.unlock(); 00180 * @endcode 00181 * 00182 * @note You cannot call this function from ISR context. 00183 */ 00184 bool wait_until(uint64_t millisec); 00185 00186 /** Wait for a notification or timeout 00187 * 00188 * @param millisec timeout value or osWaitForever in case of no time-out. 00189 * @return true if a timeout occurred, false otherwise. 00190 * 00191 * @note - The thread calling this function must be the owner of the 00192 * ConditionVariable's mutex and it must be locked exactly once 00193 * @note - Spurious notifications can occur so the caller of this API 00194 * should check to make sure the condition they are waiting on has 00195 * been met 00196 * 00197 * Example: 00198 * @code 00199 * mutex.lock(); 00200 * 00201 * while (!condition_met) { 00202 * cond.wait_for(MAX_SLEEP_TIME); 00203 * if (!condition_met) { 00204 * do_other_work_while_condition_false(); 00205 * } 00206 * } 00207 * 00208 * if (condition_met) { 00209 * function_to_handle_condition(); 00210 * } 00211 * 00212 * mutex.unlock(); 00213 * @endcode 00214 * 00215 * @note You cannot call this function from ISR context. 00216 */ 00217 bool wait_for(uint32_t millisec); 00218 00219 /** Notify one waiter on this condition variable that a condition changed. 00220 * 00221 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex 00222 * 00223 * @note You cannot call this function from ISR context. 00224 */ 00225 void notify_one(); 00226 00227 /** Notify all waiters on this condition variable that a condition changed. 00228 * 00229 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex 00230 * 00231 * @note You cannot call this function from ISR context. 00232 */ 00233 void notify_all(); 00234 00235 /** ConditionVariable destructor 00236 * 00237 * @note You cannot call this function from ISR context. 00238 */ 00239 ~ConditionVariable(); 00240 00241 protected: 00242 struct Waiter { 00243 Waiter(); 00244 Semaphore sem; 00245 Waiter *prev; 00246 Waiter *next; 00247 bool in_list; 00248 }; 00249 00250 static void _add_wait_list(Waiter **wait_list, Waiter *waiter); 00251 static void _remove_wait_list(Waiter **wait_list, Waiter *waiter); 00252 Mutex &_mutex; 00253 Waiter *_wait_list; 00254 }; 00255 00256 } 00257 #endif 00258 00259 /** @}*/
Generated on Tue Jul 12 2022 14:23:32 by
