blob: 7e9f3c638cc28cdf27a0ff567596d74ff578f7cf [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_CONDITION_H_
2#define AOS_CONDITION_H_
Brian Silvermand41b4422013-09-01 14:02:33 -07003
Austin Schuh0ad2b6f2019-06-09 21:27:07 -07004#include <chrono>
5
John Park398c74a2018-10-20 21:17:39 -07006#include "aos/ipc_lib/aos_sync.h"
Brian Silvermand41b4422013-09-01 14:02:33 -07007
8namespace aos {
9
Brian Silvermandc1eb272014-08-19 14:25:59 -040010class Mutex;
11
Brian Silvermand41b4422013-09-01 14:02:33 -070012// A condition variable (IPC mechanism where 1 process/task can notify all
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070013// others that are waiting for something to happen) without the race condition
14// where a notification is sent after some process has checked if the thing has
15// happened but before it has started listening for notifications.
16//
Brian Silvermandc1eb272014-08-19 14:25:59 -040017// This implementation will LOG(FATAL) if anything weird happens.
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070018//
19// A simple example of the use of a condition variable (adapted from
20// pthread_cond(3)):
21//
22// int x, y;
23// Mutex mutex;
24// Condition condition(&mutex);
25//
26// // Waiting until x is greater than y:
27// {
28// MutexLocker locker(&mutex);
29// while (!(x > y)) condition.Wait();
30// // do whatever
31// }
32//
33// // Modifying x and/or y:
34// {
35// MutexLocker locker(&mutex);
36// // modify x and y
37// if (x > y) condition.Broadcast();
38// }
39//
40// Notice the loop around the Wait(). This is very important because some other
41// process can lock the mutex and modify the shared state (possibly undoing
42// whatever the Wait()er was waiting for) in between the Broadcast()er unlocking
43// the mutex and the Wait()er(s) relocking it.
Brian Silvermand41b4422013-09-01 14:02:33 -070044//
Brian Silverman08661c72013-09-01 17:24:38 -070045// Multiple condition variables may be associated with the same mutex but
Brian Silvermandc1eb272014-08-19 14:25:59 -040046// exactly one mutex must be associated with each condition variable.
Brian Silvermand41b4422013-09-01 14:02:33 -070047class Condition {
48 public:
Brian Silverman797e71e2013-09-06 17:29:39 -070049 // m is the mutex that will be associated with this condition variable. This
50 // object will hold on to a reference to it but does not take ownership.
Brian Silverman08661c72013-09-01 17:24:38 -070051 explicit Condition(Mutex *m);
Brian Silvermand41b4422013-09-01 14:02:33 -070052
Austin Schuh0ad2b6f2019-06-09 21:27:07 -070053 enum class WaitResult { kOk, kOwnerDied, kTimeout };
54
Brian Silvermaneeb62ca2013-09-11 15:08:03 -070055 // Waits for the condition variable to be signalled, atomically unlocking the
56 // mutex associated with this condition variable at the same time. The mutex
57 // associated with this condition variable must be locked when this is called
58 // and will be locked when this method returns.
59 // NOTE: The relocking of the mutex is not performed atomically with waking
60 // up.
Brian Silverman71c55c52014-08-19 14:31:59 -040061 // Returns true if the previous owner of the mutex died before we relocked it.
Brian Silvermandc1eb272014-08-19 14:25:59 -040062 bool Wait() __attribute__((warn_unused_result));
Brian Silverman08661c72013-09-01 17:24:38 -070063
Austin Schuh0ad2b6f2019-06-09 21:27:07 -070064 // Waits for the condition variable to be signalled with a timeout.
65 WaitResult WaitTimed(::std::chrono::nanoseconds timeout)
66 __attribute__((warn_unused_result));
67
Brian Silvermandc1eb272014-08-19 14:25:59 -040068 // Signals approximately 1 other process currently Wait()ing on this condition
Brian Silverman08661c72013-09-01 17:24:38 -070069 // variable. Calling this does not require the mutex associated with this
70 // condition variable to be locked.
Brian Silverman797e71e2013-09-06 17:29:39 -070071 // One of the processes with the highest priority level will be woken.
Brian Silvermandc1eb272014-08-19 14:25:59 -040072 // If there aren't any waiting at the time, none will be woken. There is a
73 // small race condition in the Linux implementation that can result in more
74 // than 1 being woken.
Brian Silverman08661c72013-09-01 17:24:38 -070075 void Signal();
76 // Wakes all processes that are currently Wait()ing on this condition
77 // variable. Calling this does not require the mutex associated with this
78 // condition variable to be locked.
79 void Broadcast();
Brian Silvermand41b4422013-09-01 14:02:33 -070080
Brian Silverman797e71e2013-09-06 17:29:39 -070081 // Retrieves the mutex associated with this condition variable.
82 Mutex *m() { return m_; }
83
Brian Silvermand41b4422013-09-01 14:02:33 -070084 private:
Brian Silvermandc1eb272014-08-19 14:25:59 -040085 aos_condition impl_;
Brian Silverman08661c72013-09-01 17:24:38 -070086 Mutex *m_;
Brian Silvermand41b4422013-09-01 14:02:33 -070087};
88
89} // namespace aos
90
John Park33858a32018-09-28 23:05:48 -070091#endif // AOS_CONDITION_H_