• 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,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