1 // Copyright 2013 The Flutter 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 "flutter/fml/synchronization/waitable_event.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10
11 #include <atomic>
12 #include <thread>
13 #include <type_traits>
14 #include <vector>
15
16 #include "flutter/fml/macros.h"
17 #include "gtest/gtest.h"
18
19 namespace fml {
20 namespace {
21
22 constexpr TimeDelta kEpsilonTimeout = TimeDelta::FromMilliseconds(20);
23 constexpr TimeDelta kTinyTimeout = TimeDelta::FromMilliseconds(100);
24 constexpr TimeDelta kActionTimeout = TimeDelta::FromMilliseconds(10000);
25
26 // Sleeps for a "very small" amount of time.
27
SleepFor(TimeDelta duration)28 void SleepFor(TimeDelta duration) {
29 std::this_thread::sleep_for(
30 std::chrono::nanoseconds(duration.ToNanoseconds()));
31 }
32
EpsilonRandomSleep()33 void EpsilonRandomSleep() {
34 TimeDelta duration =
35 TimeDelta::FromMilliseconds(static_cast<unsigned>(rand()) % 20u);
36 SleepFor(duration);
37 }
38
39 // AutoResetWaitableEvent ------------------------------------------------------
40
TEST(AutoResetWaitableEventTest,Basic)41 TEST(AutoResetWaitableEventTest, Basic) {
42 AutoResetWaitableEvent ev;
43 EXPECT_FALSE(ev.IsSignaledForTest());
44 ev.Signal();
45 EXPECT_TRUE(ev.IsSignaledForTest());
46 ev.Wait();
47 EXPECT_FALSE(ev.IsSignaledForTest());
48 ev.Reset();
49 EXPECT_FALSE(ev.IsSignaledForTest());
50 ev.Signal();
51 EXPECT_TRUE(ev.IsSignaledForTest());
52 ev.Reset();
53 EXPECT_FALSE(ev.IsSignaledForTest());
54 EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::Zero()));
55 EXPECT_FALSE(ev.IsSignaledForTest());
56 EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
57 EXPECT_FALSE(ev.IsSignaledForTest());
58 ev.Signal();
59 EXPECT_TRUE(ev.IsSignaledForTest());
60 EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::Zero()));
61 EXPECT_FALSE(ev.IsSignaledForTest());
62 EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
63 EXPECT_FALSE(ev.IsSignaledForTest());
64 ev.Signal();
65 EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
66 EXPECT_FALSE(ev.IsSignaledForTest());
67 }
68
TEST(AutoResetWaitableEventTest,MultipleWaiters)69 TEST(AutoResetWaitableEventTest, MultipleWaiters) {
70 AutoResetWaitableEvent ev;
71
72 for (size_t i = 0u; i < 5u; i++) {
73 std::atomic_uint wake_count(0u);
74 std::vector<std::thread> threads;
75 for (size_t j = 0u; j < 4u; j++) {
76 threads.push_back(std::thread([&ev, &wake_count]() {
77 if (rand() % 2 == 0)
78 ev.Wait();
79 else
80 EXPECT_FALSE(ev.WaitWithTimeout(kActionTimeout));
81 wake_count.fetch_add(1u);
82 // Note: We can't say anything about the signaled state of |ev| here,
83 // since the main thread may have already signaled it again.
84 }));
85 }
86
87 // Unfortunately, we can't really wait for the threads to be waiting, so we
88 // just sleep for a bit, and count on them having started and advanced to
89 // waiting.
90 SleepFor(kTinyTimeout + kTinyTimeout);
91
92 for (size_t j = 0u; j < threads.size(); j++) {
93 unsigned old_wake_count = wake_count.load();
94 EXPECT_EQ(j, old_wake_count);
95
96 // Each |Signal()| should wake exactly one thread.
97 ev.Signal();
98
99 // Poll for |wake_count| to change.
100 while (wake_count.load() == old_wake_count)
101 SleepFor(kEpsilonTimeout);
102
103 EXPECT_FALSE(ev.IsSignaledForTest());
104
105 // And once it's changed, wait a little longer, to see if any other
106 // threads are awoken (they shouldn't be).
107 SleepFor(kEpsilonTimeout);
108
109 EXPECT_EQ(old_wake_count + 1u, wake_count.load());
110
111 EXPECT_FALSE(ev.IsSignaledForTest());
112 }
113
114 // Having done that, if we signal |ev| now, it should stay signaled.
115 ev.Signal();
116 SleepFor(kEpsilonTimeout);
117 EXPECT_TRUE(ev.IsSignaledForTest());
118
119 for (auto& thread : threads)
120 thread.join();
121
122 ev.Reset();
123 }
124 }
125
126 // ManualResetWaitableEvent ----------------------------------------------------
127
TEST(ManualResetWaitableEventTest,Basic)128 TEST(ManualResetWaitableEventTest, Basic) {
129 ManualResetWaitableEvent ev;
130 EXPECT_FALSE(ev.IsSignaledForTest());
131 ev.Signal();
132 EXPECT_TRUE(ev.IsSignaledForTest());
133 ev.Wait();
134 EXPECT_TRUE(ev.IsSignaledForTest());
135 ev.Reset();
136 EXPECT_FALSE(ev.IsSignaledForTest());
137 EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::Zero()));
138 EXPECT_FALSE(ev.IsSignaledForTest());
139 EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
140 EXPECT_FALSE(ev.IsSignaledForTest());
141 ev.Signal();
142 EXPECT_TRUE(ev.IsSignaledForTest());
143 EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::Zero()));
144 EXPECT_TRUE(ev.IsSignaledForTest());
145 EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1)));
146 EXPECT_TRUE(ev.IsSignaledForTest());
147 }
148
TEST(ManualResetWaitableEventTest,SignalMultiple)149 TEST(ManualResetWaitableEventTest, SignalMultiple) {
150 ManualResetWaitableEvent ev;
151
152 for (size_t i = 0u; i < 10u; i++) {
153 for (size_t num_waiters = 1u; num_waiters < 5u; num_waiters++) {
154 std::vector<std::thread> threads;
155 for (size_t j = 0u; j < num_waiters; j++) {
156 threads.push_back(std::thread([&ev]() {
157 EpsilonRandomSleep();
158
159 if (rand() % 2 == 0)
160 ev.Wait();
161 else
162 EXPECT_FALSE(ev.WaitWithTimeout(kActionTimeout));
163 }));
164 }
165
166 EpsilonRandomSleep();
167
168 ev.Signal();
169
170 // The threads will only terminate once they've successfully waited (or
171 // timed out).
172 for (auto& thread : threads)
173 thread.join();
174
175 ev.Reset();
176 }
177 }
178 }
179
180 } // namespace
181 } // namespace fml
182