1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include <memory>
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/atomic_sequence_num.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
11*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/test/gtest_util.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/threading/simple_thread.h"
14*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker namespace base {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker namespace {
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker class SetIntRunner : public DelegateSimpleThread::Delegate {
21*6777b538SAndroid Build Coastguard Worker public:
SetIntRunner(int * ptr,int val)22*6777b538SAndroid Build Coastguard Worker SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker SetIntRunner(const SetIntRunner&) = delete;
25*6777b538SAndroid Build Coastguard Worker SetIntRunner& operator=(const SetIntRunner&) = delete;
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker ~SetIntRunner() override = default;
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker private:
Run()30*6777b538SAndroid Build Coastguard Worker void Run() override { *ptr_ = val_; }
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker raw_ptr<int> ptr_;
33*6777b538SAndroid Build Coastguard Worker int val_;
34*6777b538SAndroid Build Coastguard Worker };
35*6777b538SAndroid Build Coastguard Worker
36*6777b538SAndroid Build Coastguard Worker // Signals |started_| when Run() is invoked and waits until |released_| is
37*6777b538SAndroid Build Coastguard Worker // signaled to return, signaling |done_| before doing so. Useful for tests that
38*6777b538SAndroid Build Coastguard Worker // care to control Run()'s flow.
39*6777b538SAndroid Build Coastguard Worker class ControlledRunner : public DelegateSimpleThread::Delegate {
40*6777b538SAndroid Build Coastguard Worker public:
ControlledRunner()41*6777b538SAndroid Build Coastguard Worker ControlledRunner()
42*6777b538SAndroid Build Coastguard Worker : started_(WaitableEvent::ResetPolicy::MANUAL,
43*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED),
44*6777b538SAndroid Build Coastguard Worker released_(WaitableEvent::ResetPolicy::MANUAL,
45*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED),
46*6777b538SAndroid Build Coastguard Worker done_(WaitableEvent::ResetPolicy::MANUAL,
47*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED) {}
48*6777b538SAndroid Build Coastguard Worker
49*6777b538SAndroid Build Coastguard Worker ControlledRunner(const ControlledRunner&) = delete;
50*6777b538SAndroid Build Coastguard Worker ControlledRunner& operator=(const ControlledRunner&) = delete;
51*6777b538SAndroid Build Coastguard Worker
~ControlledRunner()52*6777b538SAndroid Build Coastguard Worker ~ControlledRunner() override { ReleaseAndWaitUntilDone(); }
53*6777b538SAndroid Build Coastguard Worker
WaitUntilStarted()54*6777b538SAndroid Build Coastguard Worker void WaitUntilStarted() { started_.Wait(); }
55*6777b538SAndroid Build Coastguard Worker
ReleaseAndWaitUntilDone()56*6777b538SAndroid Build Coastguard Worker void ReleaseAndWaitUntilDone() {
57*6777b538SAndroid Build Coastguard Worker released_.Signal();
58*6777b538SAndroid Build Coastguard Worker done_.Wait();
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker private:
Run()62*6777b538SAndroid Build Coastguard Worker void Run() override {
63*6777b538SAndroid Build Coastguard Worker started_.Signal();
64*6777b538SAndroid Build Coastguard Worker released_.Wait();
65*6777b538SAndroid Build Coastguard Worker done_.Signal();
66*6777b538SAndroid Build Coastguard Worker }
67*6777b538SAndroid Build Coastguard Worker
68*6777b538SAndroid Build Coastguard Worker WaitableEvent started_;
69*6777b538SAndroid Build Coastguard Worker WaitableEvent released_;
70*6777b538SAndroid Build Coastguard Worker WaitableEvent done_;
71*6777b538SAndroid Build Coastguard Worker };
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker class WaitEventRunner : public DelegateSimpleThread::Delegate {
74*6777b538SAndroid Build Coastguard Worker public:
WaitEventRunner(WaitableEvent * event)75*6777b538SAndroid Build Coastguard Worker explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker WaitEventRunner(const WaitEventRunner&) = delete;
78*6777b538SAndroid Build Coastguard Worker WaitEventRunner& operator=(const WaitEventRunner&) = delete;
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker ~WaitEventRunner() override = default;
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker private:
Run()83*6777b538SAndroid Build Coastguard Worker void Run() override {
84*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(event_->IsSignaled());
85*6777b538SAndroid Build Coastguard Worker event_->Signal();
86*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(event_->IsSignaled());
87*6777b538SAndroid Build Coastguard Worker }
88*6777b538SAndroid Build Coastguard Worker
89*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> event_;
90*6777b538SAndroid Build Coastguard Worker };
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker class SeqRunner : public DelegateSimpleThread::Delegate {
93*6777b538SAndroid Build Coastguard Worker public:
SeqRunner(AtomicSequenceNumber * seq)94*6777b538SAndroid Build Coastguard Worker explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker SeqRunner(const SeqRunner&) = delete;
97*6777b538SAndroid Build Coastguard Worker SeqRunner& operator=(const SeqRunner&) = delete;
98*6777b538SAndroid Build Coastguard Worker
99*6777b538SAndroid Build Coastguard Worker private:
Run()100*6777b538SAndroid Build Coastguard Worker void Run() override { seq_->GetNext(); }
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker raw_ptr<AtomicSequenceNumber> seq_;
103*6777b538SAndroid Build Coastguard Worker };
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker // We count up on a sequence number, firing on the event when we've hit our
106*6777b538SAndroid Build Coastguard Worker // expected amount, otherwise we wait on the event. This will ensure that we
107*6777b538SAndroid Build Coastguard Worker // have all threads outstanding until we hit our expected thread pool size.
108*6777b538SAndroid Build Coastguard Worker class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
109*6777b538SAndroid Build Coastguard Worker public:
VerifyPoolRunner(AtomicSequenceNumber * seq,int total,WaitableEvent * event)110*6777b538SAndroid Build Coastguard Worker VerifyPoolRunner(AtomicSequenceNumber* seq,
111*6777b538SAndroid Build Coastguard Worker int total, WaitableEvent* event)
112*6777b538SAndroid Build Coastguard Worker : seq_(seq), total_(total), event_(event) { }
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker VerifyPoolRunner(const VerifyPoolRunner&) = delete;
115*6777b538SAndroid Build Coastguard Worker VerifyPoolRunner& operator=(const VerifyPoolRunner&) = delete;
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker private:
Run()118*6777b538SAndroid Build Coastguard Worker void Run() override {
119*6777b538SAndroid Build Coastguard Worker if (seq_->GetNext() == total_) {
120*6777b538SAndroid Build Coastguard Worker event_->Signal();
121*6777b538SAndroid Build Coastguard Worker } else {
122*6777b538SAndroid Build Coastguard Worker event_->Wait();
123*6777b538SAndroid Build Coastguard Worker }
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker raw_ptr<AtomicSequenceNumber> seq_;
127*6777b538SAndroid Build Coastguard Worker int total_;
128*6777b538SAndroid Build Coastguard Worker raw_ptr<WaitableEvent> event_;
129*6777b538SAndroid Build Coastguard Worker };
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker } // namespace
132*6777b538SAndroid Build Coastguard Worker
TEST(SimpleThreadTest,CreateAndJoin)133*6777b538SAndroid Build Coastguard Worker TEST(SimpleThreadTest, CreateAndJoin) {
134*6777b538SAndroid Build Coastguard Worker int stack_int = 0;
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Worker SetIntRunner runner(&stack_int, 7);
137*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, stack_int);
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker DelegateSimpleThread thread(&runner, "int_setter");
140*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(thread.HasBeenStarted());
141*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(thread.HasBeenJoined());
142*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(0, stack_int);
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker thread.Start();
145*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(thread.HasBeenStarted());
146*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(thread.HasBeenJoined());
147*6777b538SAndroid Build Coastguard Worker
148*6777b538SAndroid Build Coastguard Worker thread.Join();
149*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(thread.HasBeenStarted());
150*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(thread.HasBeenJoined());
151*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(7, stack_int);
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
TEST(SimpleThreadTest,WaitForEvent)154*6777b538SAndroid Build Coastguard Worker TEST(SimpleThreadTest, WaitForEvent) {
155*6777b538SAndroid Build Coastguard Worker // Create a thread, and wait for it to signal us.
156*6777b538SAndroid Build Coastguard Worker WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
157*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED);
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker WaitEventRunner runner(&event);
160*6777b538SAndroid Build Coastguard Worker DelegateSimpleThread thread(&runner, "event_waiter");
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(event.IsSignaled());
163*6777b538SAndroid Build Coastguard Worker thread.Start();
164*6777b538SAndroid Build Coastguard Worker event.Wait();
165*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(event.IsSignaled());
166*6777b538SAndroid Build Coastguard Worker thread.Join();
167*6777b538SAndroid Build Coastguard Worker }
168*6777b538SAndroid Build Coastguard Worker
TEST(SimpleThreadTest,NonJoinableStartAndDieOnJoin)169*6777b538SAndroid Build Coastguard Worker TEST(SimpleThreadTest, NonJoinableStartAndDieOnJoin) {
170*6777b538SAndroid Build Coastguard Worker ControlledRunner runner;
171*6777b538SAndroid Build Coastguard Worker
172*6777b538SAndroid Build Coastguard Worker SimpleThread::Options options;
173*6777b538SAndroid Build Coastguard Worker options.joinable = false;
174*6777b538SAndroid Build Coastguard Worker DelegateSimpleThread thread(&runner, "non_joinable", options);
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(thread.HasBeenStarted());
177*6777b538SAndroid Build Coastguard Worker thread.Start();
178*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(thread.HasBeenStarted());
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker // Note: this is not quite the same as |thread.HasBeenStarted()| which
181*6777b538SAndroid Build Coastguard Worker // represents ThreadMain() getting ready to invoke Run() whereas
182*6777b538SAndroid Build Coastguard Worker // |runner.WaitUntilStarted()| ensures Run() was actually invoked.
183*6777b538SAndroid Build Coastguard Worker runner.WaitUntilStarted();
184*6777b538SAndroid Build Coastguard Worker
185*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(thread.HasBeenJoined());
186*6777b538SAndroid Build Coastguard Worker EXPECT_DCHECK_DEATH({ thread.Join(); });
187*6777b538SAndroid Build Coastguard Worker }
188*6777b538SAndroid Build Coastguard Worker
TEST(SimpleThreadTest,NonJoinableInactiveDelegateDestructionIsOkay)189*6777b538SAndroid Build Coastguard Worker TEST(SimpleThreadTest, NonJoinableInactiveDelegateDestructionIsOkay) {
190*6777b538SAndroid Build Coastguard Worker std::unique_ptr<ControlledRunner> runner(new ControlledRunner);
191*6777b538SAndroid Build Coastguard Worker
192*6777b538SAndroid Build Coastguard Worker SimpleThread::Options options;
193*6777b538SAndroid Build Coastguard Worker options.joinable = false;
194*6777b538SAndroid Build Coastguard Worker std::unique_ptr<DelegateSimpleThread> thread(
195*6777b538SAndroid Build Coastguard Worker new DelegateSimpleThread(runner.get(), "non_joinable", options));
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker thread->Start();
198*6777b538SAndroid Build Coastguard Worker runner->WaitUntilStarted();
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker // Deleting a non-joinable SimpleThread after Run() was invoked is okay.
201*6777b538SAndroid Build Coastguard Worker thread.reset();
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker runner->WaitUntilStarted();
204*6777b538SAndroid Build Coastguard Worker runner->ReleaseAndWaitUntilDone();
205*6777b538SAndroid Build Coastguard Worker // It should be safe to destroy a Delegate after its Run() method completed.
206*6777b538SAndroid Build Coastguard Worker runner.reset();
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
TEST(SimpleThreadTest,ThreadPool)209*6777b538SAndroid Build Coastguard Worker TEST(SimpleThreadTest, ThreadPool) {
210*6777b538SAndroid Build Coastguard Worker AtomicSequenceNumber seq;
211*6777b538SAndroid Build Coastguard Worker SeqRunner runner(&seq);
212*6777b538SAndroid Build Coastguard Worker DelegateSimpleThreadPool pool("seq_runner", 10);
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Worker // Add work before we're running.
215*6777b538SAndroid Build Coastguard Worker pool.AddWork(&runner, 300);
216*6777b538SAndroid Build Coastguard Worker
217*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(seq.GetNext(), 0);
218*6777b538SAndroid Build Coastguard Worker pool.Start();
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker // Add work while we're running.
221*6777b538SAndroid Build Coastguard Worker pool.AddWork(&runner, 300);
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker pool.JoinAll();
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(seq.GetNext(), 601);
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Worker // We can reuse our pool. Verify that all 10 threads can actually run in
228*6777b538SAndroid Build Coastguard Worker // parallel, so this test will only pass if there are actually 10 threads.
229*6777b538SAndroid Build Coastguard Worker AtomicSequenceNumber seq2;
230*6777b538SAndroid Build Coastguard Worker WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
231*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED);
232*6777b538SAndroid Build Coastguard Worker // Changing 9 to 10, for example, would cause us JoinAll() to never return.
233*6777b538SAndroid Build Coastguard Worker VerifyPoolRunner verifier(&seq2, 9, &event);
234*6777b538SAndroid Build Coastguard Worker pool.Start();
235*6777b538SAndroid Build Coastguard Worker
236*6777b538SAndroid Build Coastguard Worker pool.AddWork(&verifier, 10);
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker pool.JoinAll();
239*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(seq2.GetNext(), 10);
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker } // namespace base
243