| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Provides classes with functionality analogous to (but much more limited than) | |
| 6 // Chromium's |base::WaitableEvent|, which in turn provides functionality | |
| 7 // analogous to Windows's Event. (Unlike these two, we have separate types for | |
| 8 // the manual- and auto-reset versions.) | |
| 9 | |
| 10 #ifndef MOJO_EDK_SYSTEM_WAITABLE_EVENT_H_ | |
| 11 #define MOJO_EDK_SYSTEM_WAITABLE_EVENT_H_ | |
| 12 | |
| 13 #include "mojo/edk/util/cond_var.h" | |
| 14 #include "mojo/edk/util/mutex.h" | |
| 15 #include "mojo/edk/util/thread_annotations.h" | |
| 16 #include "mojo/public/cpp/system/macros.h" | |
| 17 | |
| 18 namespace mojo { | |
| 19 namespace system { | |
| 20 | |
| 21 // AutoResetWaitableEvent ------------------------------------------------------ | |
| 22 | |
| 23 // An event that can be signaled and waited on. This version automatically | |
| 24 // returns to the unsignaled state after unblocking one waiter. (This is similar | |
| 25 // to Windows's auto-reset Event, which is also imitated by Chromium's | |
| 26 // auto-reset |base::WaitableEvent|. However, there are some limitations -- see | |
| 27 // |Signal()|.) This class is thread-safe. | |
| 28 class AutoResetWaitableEvent { | |
| 29 public: | |
| 30 AutoResetWaitableEvent() {} | |
| 31 ~AutoResetWaitableEvent() {} | |
| 32 | |
| 33 // Put the event in the signaled state. Exactly one |Wait()| will be unblocked | |
| 34 // and the event will be returned to the unsignaled state. | |
| 35 // | |
| 36 // Notes (these are arguably bugs, but not worth working around): | |
| 37 // * That |Wait()| may be one that occurs on the calling thread, *after* the | |
| 38 // call to |Signal()|. | |
| 39 // * A |Signal()|, followed by a |Reset()|, may cause *no* waiting thread to | |
| 40 // be unblocked. | |
| 41 // * We rely on pthreads's queueing for picking which waiting thread to | |
| 42 // unblock, rather than enforcing FIFO ordering. | |
| 43 void Signal(); | |
| 44 | |
| 45 // Put the event into the unsignaled state. Generally, this is not recommended | |
| 46 // on an auto-reset event (see notes above). | |
| 47 void Reset(); | |
| 48 | |
| 49 // Blocks the calling thread until the event is signaled. Upon unblocking, the | |
| 50 // event is returned to the unsignaled state, so that (unless |Reset()| is | |
| 51 // called) each |Signal()| unblocks exactly one |Wait()|. | |
| 52 void Wait(); | |
| 53 | |
| 54 // Like |Wait()|, but with a timeout. Also unblocks if |timeout_microseconds| | |
| 55 // without being signaled in which case it returns true (otherwise, it returns | |
| 56 // false). | |
| 57 bool WaitWithTimeout(uint64_t timeout_microseconds); | |
| 58 | |
| 59 // Returns whether this event is in a signaled state or not. For use in tests | |
| 60 // only (in general, this is racy). Note: Unlike | |
| 61 // |base::WaitableEvent::IsSignaled()|, this doesn't reset the signaled state. | |
| 62 bool IsSignaledForTest(); | |
| 63 | |
| 64 private: | |
| 65 util::CondVar cv_; | |
| 66 util::Mutex mutex_; | |
| 67 | |
| 68 // True if this event is in the signaled state. | |
| 69 bool signaled_ MOJO_GUARDED_BY(mutex_) = false; | |
| 70 | |
| 71 MOJO_DISALLOW_COPY_AND_ASSIGN(AutoResetWaitableEvent); | |
| 72 }; | |
| 73 | |
| 74 // ManualResetWaitableEvent ---------------------------------------------------- | |
| 75 | |
| 76 // An event that can be signaled and waited on. This version remains signaled | |
| 77 // until explicitly reset. (This is similar to Windows's manual-reset Event, | |
| 78 // which is also imitated by Chromium's manual-reset |base::WaitableEvent|.) | |
| 79 // This class is thread-safe. | |
| 80 class ManualResetWaitableEvent { | |
| 81 public: | |
| 82 ManualResetWaitableEvent() {} | |
| 83 ~ManualResetWaitableEvent() {} | |
| 84 | |
| 85 // Put the event into the unsignaled state. | |
| 86 void Reset(); | |
| 87 | |
| 88 // Put the event in the signaled state. If this is a manual-reset event, it | |
| 89 // wakes all waiting threads (blocked on |Wait()| or |WaitWithTimeout()|). | |
| 90 // Otherwise, it wakes a single waiting thread (and returns to the unsignaled | |
| 91 // state), if any; if there are none, it remains signaled. | |
| 92 void Signal(); | |
| 93 | |
| 94 // Blocks the calling thread until the event is signaled. | |
| 95 void Wait(); | |
| 96 | |
| 97 // Like |Wait()|, but with a timeout. Also unblocks if |timeout_microseconds| | |
| 98 // without being signaled in which case it returns true (otherwise, it returns | |
| 99 // false). | |
| 100 bool WaitWithTimeout(uint64_t timeout_microseconds); | |
| 101 | |
| 102 // Returns whether this event is in a signaled state or not. For use in tests | |
| 103 // only (in general, this is racy). | |
| 104 bool IsSignaledForTest(); | |
| 105 | |
| 106 private: | |
| 107 util::CondVar cv_; | |
| 108 util::Mutex mutex_; | |
| 109 | |
| 110 // True if this event is in the signaled state. | |
| 111 bool signaled_ MOJO_GUARDED_BY(mutex_) = false; | |
| 112 | |
| 113 // While |CondVar::SignalAll()| (|pthread_cond_broadcast()|) will wake all | |
| 114 // waiting threads, one has to deal with spurious wake-ups. Checking | |
| 115 // |signaled_| isn't sufficient, since another thread may have been awoken and | |
| 116 // (manually) reset |signaled_|. This is a counter that is incremented in | |
| 117 // |Signal()| before calling |CondVar::SignalAll()|. A waiting thread knows it | |
| 118 // was awoken if |signal_id_| is different from when it started waiting. | |
| 119 unsigned signal_id_ MOJO_GUARDED_BY(mutex_) = 0u; | |
| 120 | |
| 121 MOJO_DISALLOW_COPY_AND_ASSIGN(ManualResetWaitableEvent); | |
| 122 }; | |
| 123 | |
| 124 } // namespace system | |
| 125 } // namespace mojo | |
| 126 | |
| 127 #endif // MOJO_EDK_SYSTEM_WAITABLE_EVENT_H_ | |
| OLD | NEW |