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