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 |