OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |