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