mirror of https://github.com/ARMmbed/mbed-os.git
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.pull/5419/head
parent
3bb2c445ca
commit
bbefeb4432
|
@ -20,6 +20,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
#include "rtos/ConditionVariable.h"
|
||||
#include "rtos/Kernel.h"
|
||||
#include "rtos/Thread.h"
|
||||
|
||||
#include "mbed_error.h"
|
||||
|
@ -27,7 +28,6 @@
|
|||
|
||||
namespace rtos {
|
||||
|
||||
|
||||
ConditionVariable::Waiter::Waiter(): sem(0), prev(NULL), next(NULL), in_list(false)
|
||||
{
|
||||
// No initialization to do
|
||||
|
@ -64,6 +64,24 @@ bool ConditionVariable::wait_for(uint32_t millisec)
|
|||
return timeout;
|
||||
}
|
||||
|
||||
bool ConditionVariable::wait_until(uint64_t millisec)
|
||||
{
|
||||
uint64_t now = Kernel::get_ms_count();
|
||||
|
||||
if (now >= millisec) {
|
||||
// Time has already passed - standard behaviour is to
|
||||
// treat as a "try".
|
||||
return wait_for(0);
|
||||
} else if (millisec - now >= osWaitForever) {
|
||||
// Exceeds maximum delay of underlying wait_for -
|
||||
// spuriously wake after 49 days, indicating no timeout.
|
||||
wait_for(osWaitForever - 1);
|
||||
return false;
|
||||
} else {
|
||||
return wait_for(millisec - now);
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionVariable::notify_one()
|
||||
{
|
||||
MBED_ASSERT(_mutex.get_owner() == Thread::gettid());
|
||||
|
|
|
@ -150,6 +150,39 @@ public:
|
|||
*/
|
||||
void wait();
|
||||
|
||||
/** Wait for a notification until specified time
|
||||
*
|
||||
* @param millisec absolute end time referenced to Kernel::get_ms_count()
|
||||
* @return 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
|
||||
* @note - Spurious notifications can occur so the caller of this API
|
||||
* should check to make sure the condition they are waiting on has
|
||||
* been met
|
||||
*
|
||||
* Example:
|
||||
* @code
|
||||
* 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();
|
||||
* @endcode
|
||||
*
|
||||
* @note You cannot call this function from ISR context.
|
||||
*/
|
||||
bool wait_until(uint64_t millisec);
|
||||
|
||||
/** Wait for a notification or timeout
|
||||
*
|
||||
* @param millisec timeout value or osWaitForever in case of no time-out.
|
||||
|
@ -164,15 +197,12 @@ public:
|
|||
* Example:
|
||||
* @code
|
||||
* mutex.lock();
|
||||
* Timer timer;
|
||||
* timer.start();
|
||||
*
|
||||
* bool timed_out = false;
|
||||
* uint32_t time_left = TIMEOUT;
|
||||
* while (!condition_met && !timed_out) {
|
||||
* timed_out = cond.wait_for(time_left);
|
||||
* uint32_t elapsed = timer.read_ms();
|
||||
* time_left = elapsed > TIMEOUT ? 0 : TIMEOUT - elapsed;
|
||||
* while (!condition_met) {
|
||||
* cond.wait_for(MAX_SLEEP_TIME);
|
||||
* if (!condition_met) {
|
||||
* do_other_work_while_condition_false();
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* if (condition_met) {
|
||||
|
|
Loading…
Reference in New Issue