takashi kadono / Mbed OS Nucleo446_SSD1331

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Wed Oct 10 00:33:53 2018 +0000
Revision:
0:8fdf9a60065b
how to make mbed librry

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2017-2017 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
kadonotakashi 0:8fdf9a60065b 5 * of this software and associated documentation files (the "Software"), to deal
kadonotakashi 0:8fdf9a60065b 6 * in the Software without restriction, including without limitation the rights
kadonotakashi 0:8fdf9a60065b 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
kadonotakashi 0:8fdf9a60065b 8 * copies of the Software, and to permit persons to whom the Software is
kadonotakashi 0:8fdf9a60065b 9 * furnished to do so, subject to the following conditions:
kadonotakashi 0:8fdf9a60065b 10 *
kadonotakashi 0:8fdf9a60065b 11 * The above copyright notice and this permission notice shall be included in
kadonotakashi 0:8fdf9a60065b 12 * all copies or substantial portions of the Software.
kadonotakashi 0:8fdf9a60065b 13 *
kadonotakashi 0:8fdf9a60065b 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
kadonotakashi 0:8fdf9a60065b 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
kadonotakashi 0:8fdf9a60065b 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
kadonotakashi 0:8fdf9a60065b 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
kadonotakashi 0:8fdf9a60065b 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
kadonotakashi 0:8fdf9a60065b 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
kadonotakashi 0:8fdf9a60065b 20 * SOFTWARE.
kadonotakashi 0:8fdf9a60065b 21 */
kadonotakashi 0:8fdf9a60065b 22 #ifndef CONDITIONVARIABLE_H
kadonotakashi 0:8fdf9a60065b 23 #define CONDITIONVARIABLE_H
kadonotakashi 0:8fdf9a60065b 24
kadonotakashi 0:8fdf9a60065b 25 #include <stdint.h>
kadonotakashi 0:8fdf9a60065b 26 #include "cmsis_os.h"
kadonotakashi 0:8fdf9a60065b 27 #include "rtos/Mutex.h"
kadonotakashi 0:8fdf9a60065b 28 #include "rtos/Semaphore.h"
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30 #include "platform/NonCopyable.h"
kadonotakashi 0:8fdf9a60065b 31
kadonotakashi 0:8fdf9a60065b 32 namespace rtos {
kadonotakashi 0:8fdf9a60065b 33 /** \addtogroup rtos */
kadonotakashi 0:8fdf9a60065b 34 /** @{*/
kadonotakashi 0:8fdf9a60065b 35
kadonotakashi 0:8fdf9a60065b 36 struct Waiter;
kadonotakashi 0:8fdf9a60065b 37
kadonotakashi 0:8fdf9a60065b 38 /** This class provides a safe way to wait for or send notifications of condition changes
kadonotakashi 0:8fdf9a60065b 39 *
kadonotakashi 0:8fdf9a60065b 40 * This class is used in conjunction with a mutex to safely wait for or
kadonotakashi 0:8fdf9a60065b 41 * notify waiters of condition changes to a resource accessible by multiple
kadonotakashi 0:8fdf9a60065b 42 * threads.
kadonotakashi 0:8fdf9a60065b 43 *
kadonotakashi 0:8fdf9a60065b 44 * # Defined behavior
kadonotakashi 0:8fdf9a60065b 45 * - All threads waiting on the condition variable wake when
kadonotakashi 0:8fdf9a60065b 46 * ConditionVariable::notify_all is called.
kadonotakashi 0:8fdf9a60065b 47 * - If one or more threads are waiting on the condition variable at least
kadonotakashi 0:8fdf9a60065b 48 * one of them wakes when ConditionVariable::notify is called.
kadonotakashi 0:8fdf9a60065b 49 *
kadonotakashi 0:8fdf9a60065b 50 * # Undefined behavior
kadonotakashi 0:8fdf9a60065b 51 * - The thread which is unblocked on ConditionVariable::notify_one is
kadonotakashi 0:8fdf9a60065b 52 * undefined if there are multiple waiters.
kadonotakashi 0:8fdf9a60065b 53 * - The order which in which waiting threads acquire the condition variable's
kadonotakashi 0:8fdf9a60065b 54 * mutex after ConditionVariable::notify_all is called is undefined.
kadonotakashi 0:8fdf9a60065b 55 * - When ConditionVariable::notify_one or ConditionVariable::notify_all is
kadonotakashi 0:8fdf9a60065b 56 * called and there are one or more waiters and one or more threads attempting
kadonotakashi 0:8fdf9a60065b 57 * to acquire the condition variable's mutex the order in which the mutex is
kadonotakashi 0:8fdf9a60065b 58 * acquired is undefined.
kadonotakashi 0:8fdf9a60065b 59 * - The behavior of ConditionVariable::wait and ConditionVariable::wait_for
kadonotakashi 0:8fdf9a60065b 60 * is undefined if the condition variable's mutex is locked more than once by
kadonotakashi 0:8fdf9a60065b 61 * the calling thread.
kadonotakashi 0:8fdf9a60065b 62 * - Spurious notifications (not triggered by the application) can occur
kadonotakashi 0:8fdf9a60065b 63 * and it is not defined when these occur.
kadonotakashi 0:8fdf9a60065b 64 *
kadonotakashi 0:8fdf9a60065b 65 * @note Synchronization level: Thread safe
kadonotakashi 0:8fdf9a60065b 66 *
kadonotakashi 0:8fdf9a60065b 67 * Example:
kadonotakashi 0:8fdf9a60065b 68 * @code
kadonotakashi 0:8fdf9a60065b 69 * #include "mbed.h"
kadonotakashi 0:8fdf9a60065b 70 *
kadonotakashi 0:8fdf9a60065b 71 * Mutex mutex;
kadonotakashi 0:8fdf9a60065b 72 * ConditionVariable cond(mutex);
kadonotakashi 0:8fdf9a60065b 73 *
kadonotakashi 0:8fdf9a60065b 74 * // These variables are protected by locking mutex
kadonotakashi 0:8fdf9a60065b 75 * uint32_t count = 0;
kadonotakashi 0:8fdf9a60065b 76 * bool done = false;
kadonotakashi 0:8fdf9a60065b 77 *
kadonotakashi 0:8fdf9a60065b 78 * void worker_thread()
kadonotakashi 0:8fdf9a60065b 79 * {
kadonotakashi 0:8fdf9a60065b 80 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 81 * do {
kadonotakashi 0:8fdf9a60065b 82 * printf("Worker: Count %lu\r\n", count);
kadonotakashi 0:8fdf9a60065b 83 *
kadonotakashi 0:8fdf9a60065b 84 * // Wait for a condition to change
kadonotakashi 0:8fdf9a60065b 85 * cond.wait();
kadonotakashi 0:8fdf9a60065b 86 *
kadonotakashi 0:8fdf9a60065b 87 * } while (!done);
kadonotakashi 0:8fdf9a60065b 88 * printf("Worker: Exiting\r\n");
kadonotakashi 0:8fdf9a60065b 89 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 90 * }
kadonotakashi 0:8fdf9a60065b 91 *
kadonotakashi 0:8fdf9a60065b 92 * int main() {
kadonotakashi 0:8fdf9a60065b 93 * Thread thread;
kadonotakashi 0:8fdf9a60065b 94 * thread.start(worker_thread);
kadonotakashi 0:8fdf9a60065b 95 *
kadonotakashi 0:8fdf9a60065b 96 * for (int i = 0; i < 5; i++) {
kadonotakashi 0:8fdf9a60065b 97 *
kadonotakashi 0:8fdf9a60065b 98 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 99 * // Change count and notify waiters of this
kadonotakashi 0:8fdf9a60065b 100 * count++;
kadonotakashi 0:8fdf9a60065b 101 * printf("Main: Set count to %lu\r\n", count);
kadonotakashi 0:8fdf9a60065b 102 * cond.notify_all();
kadonotakashi 0:8fdf9a60065b 103 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 104 *
kadonotakashi 0:8fdf9a60065b 105 * wait(1.0);
kadonotakashi 0:8fdf9a60065b 106 * }
kadonotakashi 0:8fdf9a60065b 107 *
kadonotakashi 0:8fdf9a60065b 108 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 109 * // Change done and notify waiters of this
kadonotakashi 0:8fdf9a60065b 110 * done = true;
kadonotakashi 0:8fdf9a60065b 111 * printf("Main: Set done\r\n");
kadonotakashi 0:8fdf9a60065b 112 * cond.notify_all();
kadonotakashi 0:8fdf9a60065b 113 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 114 *
kadonotakashi 0:8fdf9a60065b 115 * thread.join();
kadonotakashi 0:8fdf9a60065b 116 * }
kadonotakashi 0:8fdf9a60065b 117 * @endcode
kadonotakashi 0:8fdf9a60065b 118 */
kadonotakashi 0:8fdf9a60065b 119 class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
kadonotakashi 0:8fdf9a60065b 120 public:
kadonotakashi 0:8fdf9a60065b 121 /** Create and Initialize a ConditionVariable object
kadonotakashi 0:8fdf9a60065b 122 *
kadonotakashi 0:8fdf9a60065b 123 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 124 */
kadonotakashi 0:8fdf9a60065b 125 ConditionVariable(Mutex &mutex);
kadonotakashi 0:8fdf9a60065b 126
kadonotakashi 0:8fdf9a60065b 127 /** Wait for a notification
kadonotakashi 0:8fdf9a60065b 128 *
kadonotakashi 0:8fdf9a60065b 129 * Wait until a notification occurs.
kadonotakashi 0:8fdf9a60065b 130 *
kadonotakashi 0:8fdf9a60065b 131 * @note - The thread calling this function must be the owner of the
kadonotakashi 0:8fdf9a60065b 132 * ConditionVariable's mutex and it must be locked exactly once
kadonotakashi 0:8fdf9a60065b 133 * @note - Spurious notifications can occur so the caller of this API
kadonotakashi 0:8fdf9a60065b 134 * should check to make sure the condition they are waiting on has
kadonotakashi 0:8fdf9a60065b 135 * been met
kadonotakashi 0:8fdf9a60065b 136 *
kadonotakashi 0:8fdf9a60065b 137 * Example:
kadonotakashi 0:8fdf9a60065b 138 * @code
kadonotakashi 0:8fdf9a60065b 139 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 140 * while (!condition_met) {
kadonotakashi 0:8fdf9a60065b 141 * cond.wait();
kadonotakashi 0:8fdf9a60065b 142 * }
kadonotakashi 0:8fdf9a60065b 143 *
kadonotakashi 0:8fdf9a60065b 144 * function_to_handle_condition();
kadonotakashi 0:8fdf9a60065b 145 *
kadonotakashi 0:8fdf9a60065b 146 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 147 * @endcode
kadonotakashi 0:8fdf9a60065b 148 *
kadonotakashi 0:8fdf9a60065b 149 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 150 */
kadonotakashi 0:8fdf9a60065b 151 void wait();
kadonotakashi 0:8fdf9a60065b 152
kadonotakashi 0:8fdf9a60065b 153 /** Wait for a notification until specified time
kadonotakashi 0:8fdf9a60065b 154 *
kadonotakashi 0:8fdf9a60065b 155 * @param millisec absolute end time referenced to Kernel::get_ms_count()
kadonotakashi 0:8fdf9a60065b 156 * @return true if a timeout occurred, false otherwise.
kadonotakashi 0:8fdf9a60065b 157 *
kadonotakashi 0:8fdf9a60065b 158 * @note - The thread calling this function must be the owner of the
kadonotakashi 0:8fdf9a60065b 159 * ConditionVariable's mutex and it must be locked exactly once
kadonotakashi 0:8fdf9a60065b 160 * @note - Spurious notifications can occur so the caller of this API
kadonotakashi 0:8fdf9a60065b 161 * should check to make sure the condition they are waiting on has
kadonotakashi 0:8fdf9a60065b 162 * been met
kadonotakashi 0:8fdf9a60065b 163 *
kadonotakashi 0:8fdf9a60065b 164 * Example:
kadonotakashi 0:8fdf9a60065b 165 * @code
kadonotakashi 0:8fdf9a60065b 166 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 167 * uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;
kadonotakashi 0:8fdf9a60065b 168 *
kadonotakashi 0:8fdf9a60065b 169 * while (!condition_met) {
kadonotakashi 0:8fdf9a60065b 170 * if (cond.wait_until(end_time)) {
kadonotakashi 0:8fdf9a60065b 171 * break;
kadonotakashi 0:8fdf9a60065b 172 * }
kadonotakashi 0:8fdf9a60065b 173 * }
kadonotakashi 0:8fdf9a60065b 174 *
kadonotakashi 0:8fdf9a60065b 175 * if (condition_met) {
kadonotakashi 0:8fdf9a60065b 176 * function_to_handle_condition();
kadonotakashi 0:8fdf9a60065b 177 * }
kadonotakashi 0:8fdf9a60065b 178 *
kadonotakashi 0:8fdf9a60065b 179 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 180 * @endcode
kadonotakashi 0:8fdf9a60065b 181 *
kadonotakashi 0:8fdf9a60065b 182 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 183 */
kadonotakashi 0:8fdf9a60065b 184 bool wait_until(uint64_t millisec);
kadonotakashi 0:8fdf9a60065b 185
kadonotakashi 0:8fdf9a60065b 186 /** Wait for a notification or timeout
kadonotakashi 0:8fdf9a60065b 187 *
kadonotakashi 0:8fdf9a60065b 188 * @param millisec timeout value or osWaitForever in case of no time-out.
kadonotakashi 0:8fdf9a60065b 189 * @return true if a timeout occurred, false otherwise.
kadonotakashi 0:8fdf9a60065b 190 *
kadonotakashi 0:8fdf9a60065b 191 * @note - The thread calling this function must be the owner of the
kadonotakashi 0:8fdf9a60065b 192 * ConditionVariable's mutex and it must be locked exactly once
kadonotakashi 0:8fdf9a60065b 193 * @note - Spurious notifications can occur so the caller of this API
kadonotakashi 0:8fdf9a60065b 194 * should check to make sure the condition they are waiting on has
kadonotakashi 0:8fdf9a60065b 195 * been met
kadonotakashi 0:8fdf9a60065b 196 *
kadonotakashi 0:8fdf9a60065b 197 * Example:
kadonotakashi 0:8fdf9a60065b 198 * @code
kadonotakashi 0:8fdf9a60065b 199 * mutex.lock();
kadonotakashi 0:8fdf9a60065b 200 *
kadonotakashi 0:8fdf9a60065b 201 * while (!condition_met) {
kadonotakashi 0:8fdf9a60065b 202 * cond.wait_for(MAX_SLEEP_TIME);
kadonotakashi 0:8fdf9a60065b 203 * if (!condition_met) {
kadonotakashi 0:8fdf9a60065b 204 * do_other_work_while_condition_false();
kadonotakashi 0:8fdf9a60065b 205 * }
kadonotakashi 0:8fdf9a60065b 206 * }
kadonotakashi 0:8fdf9a60065b 207 *
kadonotakashi 0:8fdf9a60065b 208 * if (condition_met) {
kadonotakashi 0:8fdf9a60065b 209 * function_to_handle_condition();
kadonotakashi 0:8fdf9a60065b 210 * }
kadonotakashi 0:8fdf9a60065b 211 *
kadonotakashi 0:8fdf9a60065b 212 * mutex.unlock();
kadonotakashi 0:8fdf9a60065b 213 * @endcode
kadonotakashi 0:8fdf9a60065b 214 *
kadonotakashi 0:8fdf9a60065b 215 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 216 */
kadonotakashi 0:8fdf9a60065b 217 bool wait_for(uint32_t millisec);
kadonotakashi 0:8fdf9a60065b 218
kadonotakashi 0:8fdf9a60065b 219 /** Notify one waiter on this condition variable that a condition changed.
kadonotakashi 0:8fdf9a60065b 220 *
kadonotakashi 0:8fdf9a60065b 221 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
kadonotakashi 0:8fdf9a60065b 222 *
kadonotakashi 0:8fdf9a60065b 223 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 224 */
kadonotakashi 0:8fdf9a60065b 225 void notify_one();
kadonotakashi 0:8fdf9a60065b 226
kadonotakashi 0:8fdf9a60065b 227 /** Notify all waiters on this condition variable that a condition changed.
kadonotakashi 0:8fdf9a60065b 228 *
kadonotakashi 0:8fdf9a60065b 229 * @note - The thread calling this function must be the owner of the ConditionVariable's mutex
kadonotakashi 0:8fdf9a60065b 230 *
kadonotakashi 0:8fdf9a60065b 231 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 232 */
kadonotakashi 0:8fdf9a60065b 233 void notify_all();
kadonotakashi 0:8fdf9a60065b 234
kadonotakashi 0:8fdf9a60065b 235 /** ConditionVariable destructor
kadonotakashi 0:8fdf9a60065b 236 *
kadonotakashi 0:8fdf9a60065b 237 * @note You cannot call this function from ISR context.
kadonotakashi 0:8fdf9a60065b 238 */
kadonotakashi 0:8fdf9a60065b 239 ~ConditionVariable();
kadonotakashi 0:8fdf9a60065b 240
kadonotakashi 0:8fdf9a60065b 241 protected:
kadonotakashi 0:8fdf9a60065b 242 struct Waiter {
kadonotakashi 0:8fdf9a60065b 243 Waiter();
kadonotakashi 0:8fdf9a60065b 244 Semaphore sem;
kadonotakashi 0:8fdf9a60065b 245 Waiter *prev;
kadonotakashi 0:8fdf9a60065b 246 Waiter *next;
kadonotakashi 0:8fdf9a60065b 247 bool in_list;
kadonotakashi 0:8fdf9a60065b 248 };
kadonotakashi 0:8fdf9a60065b 249
kadonotakashi 0:8fdf9a60065b 250 static void _add_wait_list(Waiter **wait_list, Waiter *waiter);
kadonotakashi 0:8fdf9a60065b 251 static void _remove_wait_list(Waiter **wait_list, Waiter *waiter);
kadonotakashi 0:8fdf9a60065b 252 Mutex &_mutex;
kadonotakashi 0:8fdf9a60065b 253 Waiter *_wait_list;
kadonotakashi 0:8fdf9a60065b 254 };
kadonotakashi 0:8fdf9a60065b 255
kadonotakashi 0:8fdf9a60065b 256 }
kadonotakashi 0:8fdf9a60065b 257 #endif
kadonotakashi 0:8fdf9a60065b 258
kadonotakashi 0:8fdf9a60065b 259 /** @}*/