• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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