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 | |
28 | void SleepFor(TimeDelta duration) { |
29 | std::this_thread::sleep_for( |
30 | std::chrono::nanoseconds(duration.ToNanoseconds())); |
31 | } |
32 | |
33 | void EpsilonRandomSleep() { |
34 | TimeDelta duration = |
35 | TimeDelta::FromMilliseconds(static_cast<unsigned>(rand()) % 20u); |
36 | SleepFor(duration); |
37 | } |
38 | |
39 | // AutoResetWaitableEvent ------------------------------------------------------ |
40 | |
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 | |
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 | } |
82 | wake_count.fetch_add(1u); |
83 | // Note: We can't say anything about the signaled state of |ev| here, |
84 | // since the main thread may have already signaled it again. |
85 | })); |
86 | } |
87 | |
88 | // Unfortunately, we can't really wait for the threads to be waiting, so we |
89 | // just sleep for a bit, and count on them having started and advanced to |
90 | // waiting. |
91 | SleepFor(kTinyTimeout + kTinyTimeout); |
92 | |
93 | for (size_t j = 0u; j < threads.size(); j++) { |
94 | unsigned old_wake_count = wake_count.load(); |
95 | EXPECT_EQ(j, old_wake_count); |
96 | |
97 | // Each |Signal()| should wake exactly one thread. |
98 | ev.Signal(); |
99 | |
100 | // Poll for |wake_count| to change. |
101 | while (wake_count.load() == old_wake_count) { |
102 | SleepFor(kEpsilonTimeout); |
103 | } |
104 | |
105 | EXPECT_FALSE(ev.IsSignaledForTest()); |
106 | |
107 | // And once it's changed, wait a little longer, to see if any other |
108 | // threads are awoken (they shouldn't be). |
109 | SleepFor(kEpsilonTimeout); |
110 | |
111 | EXPECT_EQ(old_wake_count + 1u, wake_count.load()); |
112 | |
113 | EXPECT_FALSE(ev.IsSignaledForTest()); |
114 | } |
115 | |
116 | // Having done that, if we signal |ev| now, it should stay signaled. |
117 | ev.Signal(); |
118 | SleepFor(kEpsilonTimeout); |
119 | EXPECT_TRUE(ev.IsSignaledForTest()); |
120 | |
121 | for (auto& thread : threads) { |
122 | thread.join(); |
123 | } |
124 | |
125 | ev.Reset(); |
126 | } |
127 | } |
128 | |
129 | // ManualResetWaitableEvent ---------------------------------------------------- |
130 | |
131 | TEST(ManualResetWaitableEventTest, Basic) { |
132 | ManualResetWaitableEvent ev; |
133 | EXPECT_FALSE(ev.IsSignaledForTest()); |
134 | ev.Signal(); |
135 | EXPECT_TRUE(ev.IsSignaledForTest()); |
136 | ev.Wait(); |
137 | EXPECT_TRUE(ev.IsSignaledForTest()); |
138 | ev.Reset(); |
139 | EXPECT_FALSE(ev.IsSignaledForTest()); |
140 | EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::Zero())); |
141 | EXPECT_FALSE(ev.IsSignaledForTest()); |
142 | EXPECT_TRUE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1))); |
143 | EXPECT_FALSE(ev.IsSignaledForTest()); |
144 | ev.Signal(); |
145 | EXPECT_TRUE(ev.IsSignaledForTest()); |
146 | EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::Zero())); |
147 | EXPECT_TRUE(ev.IsSignaledForTest()); |
148 | EXPECT_FALSE(ev.WaitWithTimeout(TimeDelta::FromMilliseconds(1))); |
149 | EXPECT_TRUE(ev.IsSignaledForTest()); |
150 | } |
151 | |
152 | TEST(ManualResetWaitableEventTest, SignalMultiple) { |
153 | ManualResetWaitableEvent ev; |
154 | |
155 | for (size_t i = 0u; i < 10u; i++) { |
156 | for (size_t num_waiters = 1u; num_waiters < 5u; num_waiters++) { |
157 | std::vector<std::thread> threads; |
158 | for (size_t j = 0u; j < num_waiters; j++) { |
159 | threads.push_back(std::thread([&ev]() { |
160 | EpsilonRandomSleep(); |
161 | |
162 | if (rand() % 2 == 0) { |
163 | ev.Wait(); |
164 | } else { |
165 | EXPECT_FALSE(ev.WaitWithTimeout(kActionTimeout)); |
166 | } |
167 | })); |
168 | } |
169 | |
170 | EpsilonRandomSleep(); |
171 | |
172 | ev.Signal(); |
173 | |
174 | // The threads will only terminate once they've successfully waited (or |
175 | // timed out). |
176 | for (auto& thread : threads) { |
177 | thread.join(); |
178 | } |
179 | |
180 | ev.Reset(); |
181 | } |
182 | } |
183 | } |
184 | |
185 | } // namespace |
186 | } // namespace fml |
187 | |