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.
5 #include "base/atomic_sequence_num.h"
6 #include "base/strings/string_number_conversions.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "base/threading/simple_thread.h"
9 #include "testing/gtest/include/gtest/gtest.h"
15 class SetIntRunner
: public DelegateSimpleThread::Delegate
{
17 SetIntRunner(int* ptr
, int val
) : ptr_(ptr
), val_(val
) { }
18 virtual ~SetIntRunner() { }
20 virtual void Run() OVERRIDE
{
29 class WaitEventRunner
: public DelegateSimpleThread::Delegate
{
31 explicit WaitEventRunner(WaitableEvent
* event
) : event_(event
) { }
32 virtual ~WaitEventRunner() { }
34 virtual void Run() OVERRIDE
{
35 EXPECT_FALSE(event_
->IsSignaled());
37 EXPECT_TRUE(event_
->IsSignaled());
40 WaitableEvent
* event_
;
43 class SeqRunner
: public DelegateSimpleThread::Delegate
{
45 explicit SeqRunner(AtomicSequenceNumber
* seq
) : seq_(seq
) { }
46 virtual void Run() OVERRIDE
{
51 AtomicSequenceNumber
* seq_
;
54 // We count up on a sequence number, firing on the event when we've hit our
55 // expected amount, otherwise we wait on the event. This will ensure that we
56 // have all threads outstanding until we hit our expected thread pool size.
57 class VerifyPoolRunner
: public DelegateSimpleThread::Delegate
{
59 VerifyPoolRunner(AtomicSequenceNumber
* seq
,
60 int total
, WaitableEvent
* event
)
61 : seq_(seq
), total_(total
), event_(event
) { }
63 virtual void Run() OVERRIDE
{
64 if (seq_
->GetNext() == total_
) {
72 AtomicSequenceNumber
* seq_
;
74 WaitableEvent
* event_
;
79 TEST(SimpleThreadTest
, CreateAndJoin
) {
82 SetIntRunner
runner(&stack_int
, 7);
83 EXPECT_EQ(0, stack_int
);
85 DelegateSimpleThread
thread(&runner
, "int_setter");
86 EXPECT_FALSE(thread
.HasBeenStarted());
87 EXPECT_FALSE(thread
.HasBeenJoined());
88 EXPECT_EQ(0, stack_int
);
91 EXPECT_TRUE(thread
.HasBeenStarted());
92 EXPECT_FALSE(thread
.HasBeenJoined());
95 EXPECT_TRUE(thread
.HasBeenStarted());
96 EXPECT_TRUE(thread
.HasBeenJoined());
97 EXPECT_EQ(7, stack_int
);
100 TEST(SimpleThreadTest
, WaitForEvent
) {
101 // Create a thread, and wait for it to signal us.
102 WaitableEvent
event(true, false);
104 WaitEventRunner
runner(&event
);
105 DelegateSimpleThread
thread(&runner
, "event_waiter");
107 EXPECT_FALSE(event
.IsSignaled());
110 EXPECT_TRUE(event
.IsSignaled());
114 TEST(SimpleThreadTest
, NamedWithOptions
) {
115 WaitableEvent
event(true, false);
117 WaitEventRunner
runner(&event
);
118 SimpleThread::Options options
;
119 DelegateSimpleThread
thread(&runner
, "event_waiter", options
);
120 EXPECT_EQ(thread
.name_prefix(), "event_waiter");
121 EXPECT_FALSE(event
.IsSignaled());
124 EXPECT_EQ(thread
.name_prefix(), "event_waiter");
125 EXPECT_EQ(thread
.name(),
126 std::string("event_waiter/") + IntToString(thread
.tid()));
129 EXPECT_TRUE(event
.IsSignaled());
132 // We keep the name and tid, even after the thread is gone.
133 EXPECT_EQ(thread
.name_prefix(), "event_waiter");
134 EXPECT_EQ(thread
.name(),
135 std::string("event_waiter/") + IntToString(thread
.tid()));
138 TEST(SimpleThreadTest
, ThreadPool
) {
139 AtomicSequenceNumber seq
;
140 SeqRunner
runner(&seq
);
141 DelegateSimpleThreadPool
pool("seq_runner", 10);
143 // Add work before we're running.
144 pool
.AddWork(&runner
, 300);
146 EXPECT_EQ(seq
.GetNext(), 0);
149 // Add work while we're running.
150 pool
.AddWork(&runner
, 300);
154 EXPECT_EQ(seq
.GetNext(), 601);
156 // We can reuse our pool. Verify that all 10 threads can actually run in
157 // parallel, so this test will only pass if there are actually 10 threads.
158 AtomicSequenceNumber seq2
;
159 WaitableEvent
event(true, false);
160 // Changing 9 to 10, for example, would cause us JoinAll() to never return.
161 VerifyPoolRunner
verifier(&seq2
, 9, &event
);
164 pool
.AddWork(&verifier
, 10);
167 EXPECT_EQ(seq2
.GetNext(), 10);