• 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 "base/compiler_specific.h"
10 #include "base/threading/platform_thread.h"
11 #include "base/time/time.h"
12 #include "build/build_config.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 namespace base {
16 
TEST(WaitableEventTest,ManualBasics)17 TEST(WaitableEventTest, ManualBasics) {
18   WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
19                       WaitableEvent::InitialState::NOT_SIGNALED);
20 
21   EXPECT_FALSE(event.IsSignaled());
22 
23   event.Signal();
24   EXPECT_TRUE(event.IsSignaled());
25   EXPECT_TRUE(event.IsSignaled());
26 
27   event.Reset();
28   EXPECT_FALSE(event.IsSignaled());
29   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
30 
31   event.Signal();
32   event.Wait();
33   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
34 }
35 
TEST(WaitableEventTest,AutoBasics)36 TEST(WaitableEventTest, AutoBasics) {
37   WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
38                       WaitableEvent::InitialState::NOT_SIGNALED);
39 
40   EXPECT_FALSE(event.IsSignaled());
41 
42   event.Signal();
43   EXPECT_TRUE(event.IsSignaled());
44   EXPECT_FALSE(event.IsSignaled());
45 
46   event.Reset();
47   EXPECT_FALSE(event.IsSignaled());
48   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
49 
50   event.Signal();
51   event.Wait();
52   EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
53 
54   event.Signal();
55   EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
56 }
57 
TEST(WaitableEventTest,WaitManyShortcut)58 TEST(WaitableEventTest, WaitManyShortcut) {
59   WaitableEvent* ev[5];
60   for (unsigned i = 0; i < 5; ++i) {
61     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
62                               WaitableEvent::InitialState::NOT_SIGNALED);
63   }
64 
65   ev[3]->Signal();
66   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
67 
68   ev[3]->Signal();
69   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
70 
71   ev[4]->Signal();
72   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
73 
74   ev[0]->Signal();
75   EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
76 
77   for (unsigned i = 0; i < 5; ++i)
78     delete ev[i];
79 }
80 
81 class WaitableEventSignaler : public PlatformThread::Delegate {
82  public:
WaitableEventSignaler(TimeDelta delay,WaitableEvent * event)83   WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
84       : delay_(delay),
85         event_(event) {
86   }
87 
ThreadMain()88   void ThreadMain() override {
89     PlatformThread::Sleep(delay_);
90     event_->Signal();
91   }
92 
93  private:
94   const TimeDelta delay_;
95   WaitableEvent* event_;
96 };
97 
98 // Tests that a WaitableEvent can be safely deleted when |Wait| is done without
99 // additional synchronization.
TEST(WaitableEventTest,WaitAndDelete)100 TEST(WaitableEventTest, WaitAndDelete) {
101   WaitableEvent* ev =
102       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
103                         WaitableEvent::InitialState::NOT_SIGNALED);
104 
105   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
106   PlatformThreadHandle thread;
107   PlatformThread::Create(0, &signaler, &thread);
108 
109   ev->Wait();
110   delete ev;
111 
112   PlatformThread::Join(thread);
113 }
114 
115 // Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
116 // without additional synchronization.
TEST(WaitableEventTest,WaitMany)117 TEST(WaitableEventTest, WaitMany) {
118   WaitableEvent* ev[5];
119   for (unsigned i = 0; i < 5; ++i) {
120     ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
121                               WaitableEvent::InitialState::NOT_SIGNALED);
122   }
123 
124   WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
125   PlatformThreadHandle thread;
126   PlatformThread::Create(0, &signaler, &thread);
127 
128   size_t index = WaitableEvent::WaitMany(ev, 5);
129 
130   for (unsigned i = 0; i < 5; ++i)
131     delete ev[i];
132 
133   PlatformThread::Join(thread);
134   EXPECT_EQ(2u, index);
135 }
136 
137 // Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
138 // a timeout of 0. (crbug.com/465948)
139 #if defined(OS_POSIX)
140 // crbug.com/465948 not fixed yet.
141 #define MAYBE_TimedWait DISABLED_TimedWait
142 #else
143 #define MAYBE_TimedWait TimedWait
144 #endif
TEST(WaitableEventTest,MAYBE_TimedWait)145 TEST(WaitableEventTest, MAYBE_TimedWait) {
146   WaitableEvent* ev =
147       new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
148                         WaitableEvent::InitialState::NOT_SIGNALED);
149 
150   TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
151   WaitableEventSignaler signaler(thread_delay, ev);
152   PlatformThreadHandle thread;
153   TimeTicks start = TimeTicks::Now();
154   PlatformThread::Create(0, &signaler, &thread);
155 
156   ev->TimedWait(TimeDelta::Max());
157   EXPECT_GE(TimeTicks::Now() - start, thread_delay);
158   delete ev;
159 
160   PlatformThread::Join(thread);
161 }
162 
163 }  // namespace base
164