Skip to content

Commit bbefeb4

Browse files
committed
Add ConditionVariable::wait_until
Given the 64-bit timebase, add wait_until to ConditionVariable. Move the timeout example to wait_until(), and give wait_for() an alternative example, as it's no longer the best option for a timeout. Tidy up - remove the redundant RESUME_SIGNAL definition.
1 parent 3bb2c44 commit bbefeb4

File tree

2 files changed

+58
-10
lines changed

2 files changed

+58
-10
lines changed

rtos/ConditionVariable.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@
2020
* SOFTWARE.
2121
*/
2222
#include "rtos/ConditionVariable.h"
23+
#include "rtos/Kernel.h"
2324
#include "rtos/Thread.h"
2425

2526
#include "mbed_error.h"
2627
#include "mbed_assert.h"
2728

2829
namespace rtos {
2930

30-
3131
ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false)
3232
{
3333
// No initialization to do
@@ -64,6 +64,24 @@ bool ConditionVariable::wait_for(uint32_t millisec)
6464
return timeout;
6565
}
6666

67+
bool ConditionVariable::wait_until(uint64_t millisec)
68+
{
69+
uint64_t now = Kernel::get_ms_count();
70+
71+
if (now >= millisec) {
72+
// Time has already passed - standard behaviour is to
73+
// treat as a "try".
74+
return wait_for(0);
75+
} else if (millisec - now >= osWaitForever) {
76+
// Exceeds maximum delay of underlying wait_for -
77+
// spuriously wake after 49 days, indicating no timeout.
78+
wait_for(osWaitForever - 1);
79+
return false;
80+
} else {
81+
return wait_for(millisec - now);
82+
}
83+
}
84+
6785
void ConditionVariable::notify_one()
6886
{
6987
MBED_ASSERT(_mutex.get_owner() == Thread::gettid());

rtos/ConditionVariable.h

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,39 @@ class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
150150
*/
151151
void wait();
152152

153+
/** Wait for a notification until specified time
154+
*
155+
* @param millisec absolute end time referenced to Kernel::get_ms_count()
156+
* @return true if a timeout occurred, false otherwise.
157+
*
158+
* @note - The thread calling this function must be the owner of the
159+
* ConditionVariable's mutex and it must be locked exactly once
160+
* @note - Spurious notifications can occur so the caller of this API
161+
* should check to make sure the condition they are waiting on has
162+
* been met
163+
*
164+
* Example:
165+
* @code
166+
* mutex.lock();
167+
* uint64_t end_time = Kernel::get_ms_count() + COND_WAIT_TIMEOUT;
168+
*
169+
* while (!condition_met) {
170+
* if (cond.wait_until(end_time)) {
171+
* break;
172+
* }
173+
* }
174+
*
175+
* if (condition_met) {
176+
* function_to_handle_condition();
177+
* }
178+
*
179+
* mutex.unlock();
180+
* @endcode
181+
*
182+
* @note You cannot call this function from ISR context.
183+
*/
184+
bool wait_until(uint64_t millisec);
185+
153186
/** Wait for a notification or timeout
154187
*
155188
* @param millisec timeout value or osWaitForever in case of no time-out.
@@ -164,15 +197,12 @@ class ConditionVariable : private mbed::NonCopyable<ConditionVariable> {
164197
* Example:
165198
* @code
166199
* mutex.lock();
167-
* Timer timer;
168-
* timer.start();
169-
*
170-
* bool timed_out = false;
171-
* uint32_t time_left = TIMEOUT;
172-
* while (!condition_met && !timed_out) {
173-
* timed_out = cond.wait_for(time_left);
174-
* uint32_t elapsed = timer.read_ms();
175-
* time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed;
200+
*
201+
* while (!condition_met) {
202+
* cond.wait_for(MAX_SLEEP_TIME);
203+
* if (!condition_met) {
204+
* do_other_work_while_condition_false();
205+
* }
176206
* }
177207
*
178208
* if (condition_met) {

0 commit comments

Comments
 (0)