Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(764)

Side by Side Diff: base/threading/simple_thread_unittest.cc

Issue 2204333003: Add joinable option to SimpleThread::Options as was just done for Thread. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@b1_nonjoinable_thread
Patch Set: +friend for ScopedAllowWait.. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <memory>
6
5 #include "base/atomic_sequence_num.h" 7 #include "base/atomic_sequence_num.h"
8 #include "base/memory/ptr_util.h"
6 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
7 #include "base/synchronization/waitable_event.h" 10 #include "base/synchronization/waitable_event.h"
11 #include "base/test/gtest_util.h"
12 #include "base/threading/platform_thread.h"
8 #include "base/threading/simple_thread.h" 13 #include "base/threading/simple_thread.h"
14 #include "base/time/time.h"
9 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
10 16
11 namespace base { 17 namespace base {
12 18
13 namespace { 19 namespace {
14 20
15 class SetIntRunner : public DelegateSimpleThread::Delegate { 21 class SetIntRunner : public DelegateSimpleThread::Delegate {
16 public: 22 public:
17 SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { } 23 SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
18 ~SetIntRunner() override {} 24 ~SetIntRunner() override {}
19 25
26 private:
20 void Run() override { *ptr_ = val_; } 27 void Run() override { *ptr_ = val_; }
21 28
22 private:
23 int* ptr_; 29 int* ptr_;
24 int val_; 30 int val_;
31
32 DISALLOW_COPY_AND_ASSIGN(SetIntRunner);
33 };
34
35 // Signals |started_| when Run() is invoked and waits until |released_| is
36 // signaled to return, signaling |done_| before doing so. Useful for tests that
37 // care to control Run()'s flow. Note: the WaitableEvents need to be owned by
38 // the test as neither the ControlledRunner nor Run() live long enough to
39 // fullfil this task in all tests. All tests must wait for |done_| to be
40 // signaled before destroying the provided WaitableEvents.
41 class ControlledRunner : public DelegateSimpleThread::Delegate {
42 public:
43 explicit ControlledRunner(WaitableEvent* started,
Lei Zhang 2016/08/10 21:12:38 no need for explicit
gab 2016/08/11 13:06:18 Done.
44 WaitableEvent* released,
45 WaitableEvent* done)
46 : started_(started), released_(released), done_(done) {}
47
48 private:
49 void Run() override {
50 started_->Signal();
51
52 // The WaitableEvents are guaranteed to outlive Run() but the
53 // ControlledRunner isn't after |started_| is signaled in some death tests,
54 // copy required member state to avoid user-after-frees.
Lei Zhang 2016/08/10 21:12:38 s/user/use/
gab 2016/08/11 13:06:18 Done.
55 WaitableEvent* const released_copy = released_;
56 WaitableEvent* const done_copy = done_;
57 released_copy->Wait();
58 done_copy->Signal();
59 }
60
61 WaitableEvent* const started_;
62 WaitableEvent* const released_;
63 WaitableEvent* const done_;
64
65 DISALLOW_COPY_AND_ASSIGN(ControlledRunner);
25 }; 66 };
26 67
27 class WaitEventRunner : public DelegateSimpleThread::Delegate { 68 class WaitEventRunner : public DelegateSimpleThread::Delegate {
28 public: 69 public:
29 explicit WaitEventRunner(WaitableEvent* event) : event_(event) { } 70 explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
30 ~WaitEventRunner() override {} 71 ~WaitEventRunner() override {}
31 72
73 private:
32 void Run() override { 74 void Run() override {
33 EXPECT_FALSE(event_->IsSignaled()); 75 EXPECT_FALSE(event_->IsSignaled());
34 event_->Signal(); 76 event_->Signal();
35 EXPECT_TRUE(event_->IsSignaled()); 77 EXPECT_TRUE(event_->IsSignaled());
36 } 78 }
37 private: 79
38 WaitableEvent* event_; 80 WaitableEvent* event_;
81
82 DISALLOW_COPY_AND_ASSIGN(WaitEventRunner);
39 }; 83 };
40 84
41 class SeqRunner : public DelegateSimpleThread::Delegate { 85 class SeqRunner : public DelegateSimpleThread::Delegate {
42 public: 86 public:
43 explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { } 87 explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
88
89 private:
44 void Run() override { seq_->GetNext(); } 90 void Run() override { seq_->GetNext(); }
45 91
46 private:
47 AtomicSequenceNumber* seq_; 92 AtomicSequenceNumber* seq_;
93
94 DISALLOW_COPY_AND_ASSIGN(SeqRunner);
48 }; 95 };
49 96
50 // We count up on a sequence number, firing on the event when we've hit our 97 // We count up on a sequence number, firing on the event when we've hit our
51 // expected amount, otherwise we wait on the event. This will ensure that we 98 // expected amount, otherwise we wait on the event. This will ensure that we
52 // have all threads outstanding until we hit our expected thread pool size. 99 // have all threads outstanding until we hit our expected thread pool size.
53 class VerifyPoolRunner : public DelegateSimpleThread::Delegate { 100 class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
54 public: 101 public:
55 VerifyPoolRunner(AtomicSequenceNumber* seq, 102 VerifyPoolRunner(AtomicSequenceNumber* seq,
56 int total, WaitableEvent* event) 103 int total, WaitableEvent* event)
57 : seq_(seq), total_(total), event_(event) { } 104 : seq_(seq), total_(total), event_(event) { }
58 105
106 private:
59 void Run() override { 107 void Run() override {
60 if (seq_->GetNext() == total_) { 108 if (seq_->GetNext() == total_) {
61 event_->Signal(); 109 event_->Signal();
62 } else { 110 } else {
63 event_->Wait(); 111 event_->Wait();
64 } 112 }
65 } 113 }
66 114
67 private:
68 AtomicSequenceNumber* seq_; 115 AtomicSequenceNumber* seq_;
69 int total_; 116 int total_;
70 WaitableEvent* event_; 117 WaitableEvent* event_;
118
119 DISALLOW_COPY_AND_ASSIGN(VerifyPoolRunner);
71 }; 120 };
72 121
73 } // namespace 122 } // namespace
74 123
75 TEST(SimpleThreadTest, CreateAndJoin) { 124 TEST(SimpleThreadTest, CreateAndJoin) {
76 int stack_int = 0; 125 int stack_int = 0;
77 126
78 SetIntRunner runner(&stack_int, 7); 127 SetIntRunner runner(&stack_int, 7);
79 EXPECT_EQ(0, stack_int); 128 EXPECT_EQ(0, stack_int);
80 129
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 175
127 EXPECT_TRUE(event.IsSignaled()); 176 EXPECT_TRUE(event.IsSignaled());
128 thread.Join(); 177 thread.Join();
129 178
130 // We keep the name and tid, even after the thread is gone. 179 // We keep the name and tid, even after the thread is gone.
131 EXPECT_EQ(thread.name_prefix(), "event_waiter"); 180 EXPECT_EQ(thread.name_prefix(), "event_waiter");
132 EXPECT_EQ(thread.name(), 181 EXPECT_EQ(thread.name(),
133 std::string("event_waiter/") + IntToString(thread.tid())); 182 std::string("event_waiter/") + IntToString(thread.tid()));
134 } 183 }
135 184
185 namespace {
186
187 // A test fixture which allows stepping through phases of a non-joinable
188 // DelegateSimpleThread. SimpleThreadControlledNonJoinableTest instances will
189 // remain alive at least until |done_| is signaled by the ControlledRunner's
190 // Run() method.
191 class SimpleThreadControlledNonJoinableTest : public testing::Test {
192 public:
193 SimpleThreadControlledNonJoinableTest()
194 : started_(WaitableEvent::ResetPolicy::MANUAL,
195 WaitableEvent::InitialState::NOT_SIGNALED),
196 released_(WaitableEvent::ResetPolicy::MANUAL,
197 WaitableEvent::InitialState::NOT_SIGNALED),
198 done_(WaitableEvent::ResetPolicy::MANUAL,
199 WaitableEvent::InitialState::NOT_SIGNALED) {}
200
201 void SetUp() override {
202 runner_ = MakeUnique<ControlledRunner>(&started_, &released_, &done_);
203
204 SimpleThread::Options options;
205 options.joinable = false;
206 thread_ = MakeUnique<DelegateSimpleThread>(runner_.get(), "non_joinable",
207 options);
208
209 EXPECT_FALSE(thread_->HasBeenStarted());
210 thread_->Start();
211 EXPECT_TRUE(thread_->HasBeenStarted());
212 }
213
214 void TearDown() override {
215 // Ensure |runner_| has been released and is done with the WaitableEvents
216 // provided to it.
217 ReleaseAndWaitUntilDone();
218 }
219
220 void WaitUntilStarted() { started_.Wait(); }
221
222 void ReleaseAndWaitUntilDone() {
223 released_.Signal();
224 done_.Wait();
225 }
226
227 protected:
228 std::unique_ptr<ControlledRunner> runner_;
229 std::unique_ptr<DelegateSimpleThread> thread_;
230
231 private:
232 WaitableEvent started_;
233 WaitableEvent released_;
234 WaitableEvent done_;
235
236 DISALLOW_COPY_AND_ASSIGN(SimpleThreadControlledNonJoinableTest);
237 };
238
239 } // namespace
240
241 TEST_F(SimpleThreadControlledNonJoinableTest, DieOnJoin) {
242 EXPECT_FALSE(thread_->HasBeenJoined());
243 EXPECT_DCHECK_DEATH({ thread_->Join(); });
244 }
245
246 TEST_F(SimpleThreadControlledNonJoinableTest,
247 DeathOnActiveDelegateDestruction) {
248 WaitUntilStarted();
249
250 // Non-joinable DelegateSimpleThread is allowed to go away the minute Run() is
251 // active.
252 thread_.reset();
253
254 // The Delegate can't go away while Run() is in progress however.
255 EXPECT_DCHECK_DEATH({ runner_.reset(); });
256 }
257
258 TEST_F(SimpleThreadControlledNonJoinableTest,
259 InactiveDelegateDestructionIsOkay) {
260 WaitUntilStarted();
261 ReleaseAndWaitUntilDone();
262 // The Delegate should be safe to be destroyed after its Run() method
263 // completed.
264 runner_.reset();
265 }
266
136 TEST(SimpleThreadTest, ThreadPool) { 267 TEST(SimpleThreadTest, ThreadPool) {
137 AtomicSequenceNumber seq; 268 AtomicSequenceNumber seq;
138 SeqRunner runner(&seq); 269 SeqRunner runner(&seq);
139 DelegateSimpleThreadPool pool("seq_runner", 10); 270 DelegateSimpleThreadPool pool("seq_runner", 10);
140 271
141 // Add work before we're running. 272 // Add work before we're running.
142 pool.AddWork(&runner, 300); 273 pool.AddWork(&runner, 300);
143 274
144 EXPECT_EQ(seq.GetNext(), 0); 275 EXPECT_EQ(seq.GetNext(), 0);
145 pool.Start(); 276 pool.Start();
(...skipping 14 matching lines...) Expand all
160 VerifyPoolRunner verifier(&seq2, 9, &event); 291 VerifyPoolRunner verifier(&seq2, 9, &event);
161 pool.Start(); 292 pool.Start();
162 293
163 pool.AddWork(&verifier, 10); 294 pool.AddWork(&verifier, 10);
164 295
165 pool.JoinAll(); 296 pool.JoinAll();
166 EXPECT_EQ(seq2.GetNext(), 10); 297 EXPECT_EQ(seq2.GetNext(), 10);
167 } 298 }
168 299
169 } // namespace base 300 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698