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