1 // Copyright (c) 2012 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 "base/synchronization/waitable_event.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10
11 #include "base/compiler_specific.h"
12 #include "base/threading/platform_thread.h"
13 #include "base/time/time.h"
14 #include "build/build_config.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace base {
18
TEST(WaitableEventTest,ManualBasics)19 TEST(WaitableEventTest, ManualBasics) {
20 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
21 WaitableEvent::InitialState::NOT_SIGNALED);
22
23 EXPECT_FALSE(event.IsSignaled());
24
25 event.Signal();
26 EXPECT_TRUE(event.IsSignaled());
27 EXPECT_TRUE(event.IsSignaled());
28
29 event.Reset();
30 EXPECT_FALSE(event.IsSignaled());
31 EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
32
33 event.Signal();
34 event.Wait();
35 EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
36 }
37
TEST(WaitableEventTest,ManualInitiallySignaled)38 TEST(WaitableEventTest, ManualInitiallySignaled) {
39 WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
40 WaitableEvent::InitialState::SIGNALED);
41
42 EXPECT_TRUE(event.IsSignaled());
43 EXPECT_TRUE(event.IsSignaled());
44
45 event.Reset();
46
47 EXPECT_FALSE(event.IsSignaled());
48 EXPECT_FALSE(event.IsSignaled());
49
50 event.Signal();
51
52 event.Wait();
53 EXPECT_TRUE(event.IsSignaled());
54 EXPECT_TRUE(event.IsSignaled());
55 }
56
TEST(WaitableEventTest,AutoBasics)57 TEST(WaitableEventTest, AutoBasics) {
58 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
59 WaitableEvent::InitialState::NOT_SIGNALED);
60
61 EXPECT_FALSE(event.IsSignaled());
62
63 event.Signal();
64 EXPECT_TRUE(event.IsSignaled());
65 EXPECT_FALSE(event.IsSignaled());
66
67 event.Reset();
68 EXPECT_FALSE(event.IsSignaled());
69 EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
70
71 event.Signal();
72 event.Wait();
73 EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
74
75 event.Signal();
76 EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
77 }
78
TEST(WaitableEventTest,AutoInitiallySignaled)79 TEST(WaitableEventTest, AutoInitiallySignaled) {
80 WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
81 WaitableEvent::InitialState::SIGNALED);
82
83 EXPECT_TRUE(event.IsSignaled());
84 EXPECT_FALSE(event.IsSignaled());
85
86 event.Signal();
87
88 EXPECT_TRUE(event.IsSignaled());
89 EXPECT_FALSE(event.IsSignaled());
90 }
91
TEST(WaitableEventTest,WaitManyShortcut)92 TEST(WaitableEventTest, WaitManyShortcut) {
93 WaitableEvent* ev[5];
94 for (unsigned i = 0; i < 5; ++i) {
95 ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
96 WaitableEvent::InitialState::NOT_SIGNALED);
97 }
98
99 ev[3]->Signal();
100 EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
101
102 ev[3]->Signal();
103 EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
104
105 ev[4]->Signal();
106 EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
107
108 ev[0]->Signal();
109 EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
110
111 for (unsigned i = 0; i < 5; ++i)
112 delete ev[i];
113 }
114
TEST(WaitableEventTest,WaitManyLeftToRight)115 TEST(WaitableEventTest, WaitManyLeftToRight) {
116 WaitableEvent* ev[5];
117 for (size_t i = 0; i < 5; ++i) {
118 ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
119 WaitableEvent::InitialState::NOT_SIGNALED);
120 }
121
122 // Test for consistent left-to-right return behavior across all permutations
123 // of the input array. This is to verify that only the indices -- and not
124 // the WaitableEvents' addresses -- are relevant in determining who wins when
125 // multiple events are signaled.
126
127 std::sort(ev, ev + 5);
128 do {
129 ev[0]->Signal();
130 ev[1]->Signal();
131 EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
132
133 ev[2]->Signal();
134 EXPECT_EQ(1u, WaitableEvent::WaitMany(ev, 5));
135 EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
136
137 ev[3]->Signal();
138 ev[4]->Signal();
139 ev[0]->Signal();
140 EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
141 EXPECT_EQ(3u, WaitableEvent::WaitMany(ev, 5));
142 ev[2]->Signal();
143 EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
144 EXPECT_EQ(4u, WaitableEvent::WaitMany(ev, 5));
145 } while (std::next_permutation(ev, ev + 5));
146
147 for (size_t i = 0; i < 5; ++i)
148 delete ev[i];
149 }
150
151 class WaitableEventSignaler : public PlatformThread::Delegate {
152 public:
WaitableEventSignaler(TimeDelta delay,WaitableEvent * event)153 WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
154 : delay_(delay),
155 event_(event) {
156 }
157
ThreadMain()158 void ThreadMain() override {
159 PlatformThread::Sleep(delay_);
160 event_->Signal();
161 }
162
163 private:
164 const TimeDelta delay_;
165 WaitableEvent* event_;
166 };
167
168 // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
169 // additional synchronization.
TEST(WaitableEventTest,WaitAndDelete)170 TEST(WaitableEventTest, WaitAndDelete) {
171 WaitableEvent* ev =
172 new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
173 WaitableEvent::InitialState::NOT_SIGNALED);
174
175 WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
176 PlatformThreadHandle thread;
177 PlatformThread::Create(0, &signaler, &thread);
178
179 ev->Wait();
180 delete ev;
181
182 PlatformThread::Join(thread);
183 }
184
185 // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
186 // without additional synchronization.
TEST(WaitableEventTest,WaitMany)187 TEST(WaitableEventTest, WaitMany) {
188 WaitableEvent* ev[5];
189 for (unsigned i = 0; i < 5; ++i) {
190 ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
191 WaitableEvent::InitialState::NOT_SIGNALED);
192 }
193
194 WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
195 PlatformThreadHandle thread;
196 PlatformThread::Create(0, &signaler, &thread);
197
198 size_t index = WaitableEvent::WaitMany(ev, 5);
199
200 for (unsigned i = 0; i < 5; ++i)
201 delete ev[i];
202
203 PlatformThread::Join(thread);
204 EXPECT_EQ(2u, index);
205 }
206
207 // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
208 // a timeout of 0. (crbug.com/465948)
TEST(WaitableEventTest,TimedWait)209 TEST(WaitableEventTest, TimedWait) {
210 WaitableEvent* ev =
211 new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
212 WaitableEvent::InitialState::NOT_SIGNALED);
213
214 TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
215 WaitableEventSignaler signaler(thread_delay, ev);
216 PlatformThreadHandle thread;
217 TimeTicks start = TimeTicks::Now();
218 PlatformThread::Create(0, &signaler, &thread);
219
220 EXPECT_TRUE(ev->TimedWait(TimeDelta::Max()));
221 EXPECT_GE(TimeTicks::Now() - start, thread_delay);
222 delete ev;
223
224 PlatformThread::Join(thread);
225 }
226
227 // Tests that a sub-ms TimedWait doesn't time out promptly.
TEST(WaitableEventTest,SubMsTimedWait)228 TEST(WaitableEventTest, SubMsTimedWait) {
229 WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
230 WaitableEvent::InitialState::NOT_SIGNALED);
231
232 TimeDelta delay = TimeDelta::FromMicroseconds(900);
233 TimeTicks start_time = TimeTicks::Now();
234 ev.TimedWait(delay);
235 EXPECT_GE(TimeTicks::Now() - start_time, delay);
236 }
237
238 // Tests that TimedWaitUntil can be safely used with various end_time deadline
239 // values.
TEST(WaitableEventTest,TimedWaitUntil)240 TEST(WaitableEventTest, TimedWaitUntil) {
241 WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
242 WaitableEvent::InitialState::NOT_SIGNALED);
243
244 TimeTicks start_time(TimeTicks::Now());
245 TimeDelta delay = TimeDelta::FromMilliseconds(10);
246
247 // Should be OK to wait for the current time or time in the past.
248 // That should end promptly and be equivalent to IsSignalled.
249 EXPECT_FALSE(ev.TimedWaitUntil(start_time));
250 EXPECT_FALSE(ev.TimedWaitUntil(start_time - delay));
251
252 // Should be OK to wait for zero TimeTicks().
253 EXPECT_FALSE(ev.TimedWaitUntil(TimeTicks()));
254
255 // Waiting for a time in the future shouldn't end before the deadline
256 // if the event isn't signalled.
257 EXPECT_FALSE(ev.TimedWaitUntil(start_time + delay));
258 EXPECT_GE(TimeTicks::Now() - start_time, delay);
259
260 // Test that passing TimeTicks::Max to TimedWaitUntil is valid and isn't
261 // the same as passing TimeTicks(). Also verifies that signaling event
262 // ends the wait promptly.
263 WaitableEventSignaler signaler(delay, &ev);
264 PlatformThreadHandle thread;
265 start_time = TimeTicks::Now();
266 PlatformThread::Create(0, &signaler, &thread);
267
268 EXPECT_TRUE(ev.TimedWaitUntil(TimeTicks::Max()));
269 EXPECT_GE(TimeTicks::Now() - start_time, delay);
270
271 PlatformThread::Join(thread);
272 }
273
274 } // namespace base
275