blob: 7e9f3c638cc28cdf27a0ff567596d74ff578f7cf [file] [log] [blame]
#ifndef AOS_CONDITION_H_
#define AOS_CONDITION_H_
#include <chrono>
#include "aos/ipc_lib/aos_sync.h"
namespace aos {
class Mutex;
// A condition variable (IPC mechanism where 1 process/task can notify all
// others that are waiting for something to happen) without the race condition
// where a notification is sent after some process has checked if the thing has
// happened but before it has started listening for notifications.
//
// This implementation will LOG(FATAL) if anything weird happens.
//
// A simple example of the use of a condition variable (adapted from
// pthread_cond(3)):
//
// int x, y;
// Mutex mutex;
// Condition condition(&mutex);
//
// // Waiting until x is greater than y:
// {
// MutexLocker locker(&mutex);
// while (!(x > y)) condition.Wait();
// // do whatever
// }
//
// // Modifying x and/or y:
// {
// MutexLocker locker(&mutex);
// // modify x and y
// if (x > y) condition.Broadcast();
// }
//
// Notice the loop around the Wait(). This is very important because some other
// process can lock the mutex and modify the shared state (possibly undoing
// whatever the Wait()er was waiting for) in between the Broadcast()er unlocking
// the mutex and the Wait()er(s) relocking it.
//
// Multiple condition variables may be associated with the same mutex but
// exactly one mutex must be associated with each condition variable.
class Condition {
public:
// m is the mutex that will be associated with this condition variable. This
// object will hold on to a reference to it but does not take ownership.
explicit Condition(Mutex *m);
enum class WaitResult { kOk, kOwnerDied, kTimeout };
// Waits for the condition variable to be signalled, atomically unlocking the
// mutex associated with this condition variable at the same time. The mutex
// associated with this condition variable must be locked when this is called
// and will be locked when this method returns.
// NOTE: The relocking of the mutex is not performed atomically with waking
// up.
// Returns true if the previous owner of the mutex died before we relocked it.
bool Wait() __attribute__((warn_unused_result));
// Waits for the condition variable to be signalled with a timeout.
WaitResult WaitTimed(::std::chrono::nanoseconds timeout)
__attribute__((warn_unused_result));
// Signals approximately 1 other process currently Wait()ing on this condition
// variable. Calling this does not require the mutex associated with this
// condition variable to be locked.
// One of the processes with the highest priority level will be woken.
// If there aren't any waiting at the time, none will be woken. There is a
// small race condition in the Linux implementation that can result in more
// than 1 being woken.
void Signal();
// Wakes all processes that are currently Wait()ing on this condition
// variable. Calling this does not require the mutex associated with this
// condition variable to be locked.
void Broadcast();
// Retrieves the mutex associated with this condition variable.
Mutex *m() { return m_; }
private:
aos_condition impl_;
Mutex *m_;
};
} // namespace aos
#endif // AOS_CONDITION_H_