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