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