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 ControlledRunner(WaitableEvent* started, |
| 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 use-after-frees. |
| 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 |