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