1// Copyright (c) 2006-2008 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 "base/atomic_sequence_num.h" 6#include "base/lock.h" 7#include "base/simple_thread.h" 8#include "base/string_util.h" 9#include "base/waitable_event.h" 10#include "testing/gtest/include/gtest/gtest.h" 11 12namespace { 13 14class SetIntRunner : public base::DelegateSimpleThread::Delegate { 15 public: 16 SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { } 17 ~SetIntRunner() { } 18 19 virtual void Run() { 20 *ptr_ = val_; 21 } 22 23 private: 24 int* ptr_; 25 int val_; 26}; 27 28class WaitEventRunner : public base::DelegateSimpleThread::Delegate { 29 public: 30 explicit WaitEventRunner(base::WaitableEvent* event) : event_(event) { } 31 ~WaitEventRunner() { } 32 33 virtual void Run() { 34 EXPECT_FALSE(event_->IsSignaled()); 35 event_->Signal(); 36 EXPECT_TRUE(event_->IsSignaled()); 37 } 38 private: 39 base::WaitableEvent* event_; 40}; 41 42class SeqRunner : public base::DelegateSimpleThread::Delegate { 43 public: 44 explicit SeqRunner(base::AtomicSequenceNumber* seq) : seq_(seq) { } 45 virtual void Run() { 46 seq_->GetNext(); 47 } 48 49 private: 50 base::AtomicSequenceNumber* seq_; 51}; 52 53// We count up on a sequence number, firing on the event when we've hit our 54// expected amount, otherwise we wait on the event. This will ensure that we 55// have all threads outstanding until we hit our expected thread pool size. 56class VerifyPoolRunner : public base::DelegateSimpleThread::Delegate { 57 public: 58 VerifyPoolRunner(base::AtomicSequenceNumber* seq, 59 int total, base::WaitableEvent* event) 60 : seq_(seq), total_(total), event_(event) { } 61 62 virtual void Run() { 63 if (seq_->GetNext() == total_) { 64 event_->Signal(); 65 } else { 66 event_->Wait(); 67 } 68 } 69 70 private: 71 base::AtomicSequenceNumber* seq_; 72 int total_; 73 base::WaitableEvent* event_; 74}; 75 76} // namespace 77 78TEST(SimpleThreadTest, CreateAndJoin) { 79 int stack_int = 0; 80 81 SetIntRunner runner(&stack_int, 7); 82 EXPECT_EQ(0, stack_int); 83 84 base::DelegateSimpleThread thread(&runner, "int_setter"); 85 EXPECT_FALSE(thread.HasBeenStarted()); 86 EXPECT_FALSE(thread.HasBeenJoined()); 87 EXPECT_EQ(0, stack_int); 88 89 thread.Start(); 90 EXPECT_TRUE(thread.HasBeenStarted()); 91 EXPECT_FALSE(thread.HasBeenJoined()); 92 93 thread.Join(); 94 EXPECT_TRUE(thread.HasBeenStarted()); 95 EXPECT_TRUE(thread.HasBeenJoined()); 96 EXPECT_EQ(7, stack_int); 97} 98 99TEST(SimpleThreadTest, WaitForEvent) { 100 // Create a thread, and wait for it to signal us. 101 base::WaitableEvent event(true, false); 102 103 WaitEventRunner runner(&event); 104 base::DelegateSimpleThread thread(&runner, "event_waiter"); 105 106 EXPECT_FALSE(event.IsSignaled()); 107 thread.Start(); 108 event.Wait(); 109 EXPECT_TRUE(event.IsSignaled()); 110 thread.Join(); 111} 112 113TEST(SimpleThreadTest, NamedWithOptions) { 114 base::WaitableEvent event(true, false); 115 116 WaitEventRunner runner(&event); 117 base::SimpleThread::Options options; 118 base::DelegateSimpleThread thread(&runner, "event_waiter", options); 119 EXPECT_EQ(thread.name_prefix(), "event_waiter"); 120 EXPECT_FALSE(event.IsSignaled()); 121 122 thread.Start(); 123 EXPECT_EQ(thread.name_prefix(), "event_waiter"); 124 EXPECT_EQ(thread.name(), std::string("event_waiter/") + 125 IntToString(thread.tid())); 126 event.Wait(); 127 128 EXPECT_TRUE(event.IsSignaled()); 129 thread.Join(); 130 131 // We keep the name and tid, even after the thread is gone. 132 EXPECT_EQ(thread.name_prefix(), "event_waiter"); 133 EXPECT_EQ(thread.name(), std::string("event_waiter/") + 134 IntToString(thread.tid())); 135} 136 137TEST(SimpleThreadTest, ThreadPool) { 138 base::AtomicSequenceNumber seq; 139 SeqRunner runner(&seq); 140 base::DelegateSimpleThreadPool pool("seq_runner", 10); 141 142 // Add work before we're running. 143 pool.AddWork(&runner, 300); 144 145 EXPECT_EQ(seq.GetNext(), 0); 146 pool.Start(); 147 148 // Add work while we're running. 149 pool.AddWork(&runner, 300); 150 151 pool.JoinAll(); 152 153 EXPECT_EQ(seq.GetNext(), 601); 154 155 // We can reuse our pool. Verify that all 10 threads can actually run in 156 // parallel, so this test will only pass if there are actually 10 threads. 157 base::AtomicSequenceNumber seq2; 158 base::WaitableEvent event(true, false); 159 // Changing 9 to 10, for example, would cause us JoinAll() to never return. 160 VerifyPoolRunner verifier(&seq2, 9, &event); 161 pool.Start(); 162 163 pool.AddWork(&verifier, 10); 164 165 pool.JoinAll(); 166 EXPECT_EQ(seq2.GetNext(), 10); 167} 168