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