Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(48)

Side by Side Diff: mojo/edk/util/waitable_event.cc

Issue 1420713006: Revert "EDK: Move //mojo/edk/system/waitable_event* to edk/util." (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/util/waitable_event.h ('k') | mojo/edk/util/waitable_event_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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 #include "mojo/edk/util/waitable_event.h"
6
7 #include <errno.h>
8 #include <time.h>
9
10 #include "mojo/edk/util/logging_internal.h"
11
12 namespace mojo {
13 namespace util {
14
15 namespace {
16
17 // Returns the number of microseconds elapsed since epoch start (according to a
18 // monotonic clock).
19 uint64_t Now() {
20 const uint64_t kMicrosecondsPerSecond = 1000000ULL;
21 const uint64_t kNanosecondsPerMicrosecond = 1000ULL;
22
23 struct timespec now;
24 int error = clock_gettime(CLOCK_MONOTONIC, &now);
25 INTERNAL_DCHECK_WITH_ERRNO(!error, "clock_gettime", errno);
26 INTERNAL_DCHECK(now.tv_sec >= 0);
27 INTERNAL_DCHECK(now.tv_nsec >= 0);
28
29 return static_cast<uint64_t>(now.tv_sec) * kMicrosecondsPerSecond +
30 static_cast<uint64_t>(now.tv_nsec) / kNanosecondsPerMicrosecond;
31 }
32
33 // Waits with a timeout on |condition()|. Returns true on timeout, or false if
34 // |condition()| ever returns true. |condition()| should have no side effects
35 // (and will always be called with |*mutex| held).
36 template <typename ConditionFn>
37 bool WaitWithTimeoutImpl(Mutex* mutex,
38 CondVar* cv,
39 ConditionFn condition,
40 uint64_t timeout_microseconds)
41 MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex) {
42 mutex->AssertHeld();
43
44 if (condition())
45 return false;
46
47 // We may get spurious wakeups.
48 uint64_t wait_remaining = timeout_microseconds;
49 uint64_t start = Now();
50 while (true) {
51 if (cv->WaitWithTimeout(mutex, wait_remaining))
52 return true; // Definitely timed out.
53
54 // We may have been awoken.
55 if (condition())
56 return false;
57
58 // Or the wakeup may have been spurious.
59 uint64_t now = Now();
60 INTERNAL_DCHECK(now >= start);
61 uint64_t elapsed = now - start;
62 // It's possible that we may have timed out anyway.
63 if (elapsed >= timeout_microseconds)
64 return true;
65
66 // Otherwise, recalculate the amount that we have left to wait.
67 wait_remaining = timeout_microseconds - elapsed;
68 }
69 }
70
71 } // namespace
72
73 // AutoResetWaitableEvent ------------------------------------------------------
74
75 void AutoResetWaitableEvent::Signal() {
76 MutexLocker locker(&mutex_);
77 signaled_ = true;
78 cv_.Signal();
79 }
80
81 void AutoResetWaitableEvent::Reset() {
82 MutexLocker locker(&mutex_);
83 signaled_ = false;
84 }
85
86 void AutoResetWaitableEvent::Wait() {
87 MutexLocker locker(&mutex_);
88 while (!signaled_)
89 cv_.Wait(&mutex_);
90 signaled_ = false;
91 }
92
93 bool AutoResetWaitableEvent::WaitWithTimeout(uint64_t timeout_microseconds) {
94 MutexLocker locker(&mutex_);
95
96 if (signaled_) {
97 signaled_ = false;
98 return false;
99 }
100
101 // We may get spurious wakeups.
102 uint64_t wait_remaining = timeout_microseconds;
103 uint64_t start = Now();
104 while (true) {
105 if (cv_.WaitWithTimeout(&mutex_, wait_remaining))
106 return true; // Definitely timed out.
107
108 // We may have been awoken.
109 if (signaled_)
110 break;
111
112 // Or the wakeup may have been spurious.
113 uint64_t now = Now();
114 INTERNAL_DCHECK(now >= start);
115 uint64_t elapsed = now - start;
116 // It's possible that we may have timed out anyway.
117 if (elapsed >= timeout_microseconds)
118 return true;
119
120 // Otherwise, recalculate the amount that we have left to wait.
121 wait_remaining = timeout_microseconds - elapsed;
122 }
123
124 signaled_ = false;
125 return false;
126 }
127
128 bool AutoResetWaitableEvent::IsSignaledForTest() {
129 MutexLocker locker(&mutex_);
130 return signaled_;
131 }
132
133 // ManualResetWaitableEvent ----------------------------------------------------
134
135 void ManualResetWaitableEvent::Signal() {
136 MutexLocker locker(&mutex_);
137 signaled_ = true;
138 signal_id_++;
139 cv_.SignalAll();
140 }
141
142 void ManualResetWaitableEvent::Reset() {
143 MutexLocker locker(&mutex_);
144 signaled_ = false;
145 }
146
147 void ManualResetWaitableEvent::Wait() {
148 MutexLocker locker(&mutex_);
149
150 if (signaled_)
151 return;
152
153 auto last_signal_id = signal_id_;
154 do {
155 cv_.Wait(&mutex_);
156 } while (signal_id_ == last_signal_id);
157 }
158
159 bool ManualResetWaitableEvent::WaitWithTimeout(uint64_t timeout_microseconds) {
160 MutexLocker locker(&mutex_);
161
162 auto last_signal_id = signal_id_;
163 // Disable thread-safety analysis for the lambda: We could annotate it with
164 // |MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_)|, but then the analyzer currently
165 // isn't able to figure out that |WaitWithTimeoutImpl()| calls it while
166 // holding |mutex_|.
167 bool rv = WaitWithTimeoutImpl(
168 &mutex_, &cv_, [this, last_signal_id]() MOJO_NO_THREAD_SAFETY_ANALYSIS {
169 // Also check |signaled_| in case we're already signaled.
170 return signaled_ || signal_id_ != last_signal_id;
171 }, timeout_microseconds);
172 INTERNAL_DCHECK(rv || signaled_ || signal_id_ != last_signal_id);
173 return rv;
174 }
175
176 bool ManualResetWaitableEvent::IsSignaledForTest() {
177 MutexLocker locker(&mutex_);
178 return signaled_;
179 }
180
181 } // namespace util
182 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/util/waitable_event.h ('k') | mojo/edk/util/waitable_event_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698