Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 1 | #ifndef AOS_COMMON_CONDITION_H_ |
| 2 | #define AOS_COMMON_CONDITION_H_ |
| 3 | |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 4 | #include "aos/common/mutex.h" |
Brian Silverman | 14fd0fb | 2014-01-14 21:42:01 -0800 | [diff] [blame] | 5 | #include "aos/linux_code/ipc_lib/aos_sync.h" |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 6 | |
| 7 | namespace aos { |
| 8 | |
| 9 | // A condition variable (IPC mechanism where 1 process/task can notify all |
Brian Silverman | eeb62ca | 2013-09-11 15:08:03 -0700 | [diff] [blame] | 10 | // others that are waiting for something to happen) without the race condition |
| 11 | // where a notification is sent after some process has checked if the thing has |
| 12 | // happened but before it has started listening for notifications. |
| 13 | // |
| 14 | // This implementation will print debugging information and abort the process |
| 15 | // if anything weird happens. |
| 16 | // |
| 17 | // A simple example of the use of a condition variable (adapted from |
| 18 | // pthread_cond(3)): |
| 19 | // |
| 20 | // int x, y; |
| 21 | // Mutex mutex; |
| 22 | // Condition condition(&mutex); |
| 23 | // |
| 24 | // // Waiting until x is greater than y: |
| 25 | // { |
| 26 | // MutexLocker locker(&mutex); |
| 27 | // while (!(x > y)) condition.Wait(); |
| 28 | // // do whatever |
| 29 | // } |
| 30 | // |
| 31 | // // Modifying x and/or y: |
| 32 | // { |
| 33 | // MutexLocker locker(&mutex); |
| 34 | // // modify x and y |
| 35 | // if (x > y) condition.Broadcast(); |
| 36 | // } |
| 37 | // |
| 38 | // Notice the loop around the Wait(). This is very important because some other |
| 39 | // process can lock the mutex and modify the shared state (possibly undoing |
| 40 | // whatever the Wait()er was waiting for) in between the Broadcast()er unlocking |
| 41 | // the mutex and the Wait()er(s) relocking it. |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 42 | // |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 43 | // Multiple condition variables may be associated with the same mutex but |
| 44 | // exactly 1 mutex must be associated with each condition variable. |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 45 | class Condition { |
| 46 | public: |
Brian Silverman | 797e71e | 2013-09-06 17:29:39 -0700 | [diff] [blame] | 47 | // m is the mutex that will be associated with this condition variable. This |
| 48 | // object will hold on to a reference to it but does not take ownership. |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 49 | explicit Condition(Mutex *m); |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 50 | |
Brian Silverman | eeb62ca | 2013-09-11 15:08:03 -0700 | [diff] [blame] | 51 | // Waits for the condition variable to be signalled, atomically unlocking the |
| 52 | // mutex associated with this condition variable at the same time. The mutex |
| 53 | // associated with this condition variable must be locked when this is called |
| 54 | // and will be locked when this method returns. |
| 55 | // NOTE: The relocking of the mutex is not performed atomically with waking |
| 56 | // up. |
Austin Schuh | f4b194e | 2014-09-21 10:26:41 -0700 | [diff] [blame^] | 57 | // Returns false. |
| 58 | bool Wait(); |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 59 | |
| 60 | // Signals at most 1 other process currently Wait()ing on this condition |
| 61 | // variable. Calling this does not require the mutex associated with this |
| 62 | // condition variable to be locked. |
Brian Silverman | 797e71e | 2013-09-06 17:29:39 -0700 | [diff] [blame] | 63 | // One of the processes with the highest priority level will be woken. |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 64 | void Signal(); |
| 65 | // Wakes all processes that are currently Wait()ing on this condition |
| 66 | // variable. Calling this does not require the mutex associated with this |
| 67 | // condition variable to be locked. |
| 68 | void Broadcast(); |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 69 | |
Brian Silverman | 797e71e | 2013-09-06 17:29:39 -0700 | [diff] [blame] | 70 | // Retrieves the mutex associated with this condition variable. |
| 71 | Mutex *m() { return m_; } |
| 72 | |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 73 | private: |
Brian Silverman | 797e71e | 2013-09-06 17:29:39 -0700 | [diff] [blame] | 74 | mutex impl_; |
Brian Silverman | 08661c7 | 2013-09-01 17:24:38 -0700 | [diff] [blame] | 75 | Mutex *m_; |
Brian Silverman | d41b442 | 2013-09-01 14:02:33 -0700 | [diff] [blame] | 76 | }; |
| 77 | |
| 78 | } // namespace aos |
| 79 | |
| 80 | #endif // AOS_COMMON_CONDITION_H_ |