• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2010 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/threading/simple_thread.h"
6 
7 #include "base/logging.h"
8 #include "base/threading/platform_thread.h"
9 #include "base/string_number_conversions.h"
10 
11 namespace base {
12 
SimpleThread(const std::string & name_prefix)13 SimpleThread::SimpleThread(const std::string& name_prefix)
14     : name_prefix_(name_prefix), name_(name_prefix),
15       thread_(), event_(true, false), tid_(0), joined_(false) {
16 }
17 
SimpleThread(const std::string & name_prefix,const Options & options)18 SimpleThread::SimpleThread(const std::string& name_prefix,
19                            const Options& options)
20     : name_prefix_(name_prefix), name_(name_prefix), options_(options),
21       thread_(), event_(true, false), tid_(0), joined_(false) {
22 }
23 
~SimpleThread()24 SimpleThread::~SimpleThread() {
25   DCHECK(HasBeenStarted()) << "SimpleThread was never started.";
26   DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed.";
27 }
28 
Start()29 void SimpleThread::Start() {
30   DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times.";
31   bool success = PlatformThread::Create(options_.stack_size(), this, &thread_);
32   CHECK(success);
33   event_.Wait();  // Wait for the thread to complete initialization.
34 }
35 
Join()36 void SimpleThread::Join() {
37   DCHECK(HasBeenStarted()) << "Tried to Join a never-started thread.";
38   DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times.";
39   PlatformThread::Join(thread_);
40   joined_ = true;
41 }
42 
ThreadMain()43 void SimpleThread::ThreadMain() {
44   tid_ = PlatformThread::CurrentId();
45   // Construct our full name of the form "name_prefix_/TID".
46   name_.push_back('/');
47   name_.append(IntToString(tid_));
48   PlatformThread::SetName(name_.c_str());
49 
50   // We've initialized our new thread, signal that we're done to Start().
51   event_.Signal();
52 
53   Run();
54 }
55 
DelegateSimpleThread(Delegate * delegate,const std::string & name_prefix)56 DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate,
57                                            const std::string& name_prefix)
58     : SimpleThread(name_prefix),
59       delegate_(delegate) {
60 }
61 
DelegateSimpleThread(Delegate * delegate,const std::string & name_prefix,const Options & options)62 DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate,
63                                            const std::string& name_prefix,
64                                            const Options& options)
65     : SimpleThread(name_prefix, options),
66       delegate_(delegate) {
67 }
68 
~DelegateSimpleThread()69 DelegateSimpleThread::~DelegateSimpleThread() {
70 }
71 
Run()72 void DelegateSimpleThread::Run() {
73   DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)";
74   delegate_->Run();
75   delegate_ = NULL;
76 }
77 
DelegateSimpleThreadPool(const std::string & name_prefix,int num_threads)78 DelegateSimpleThreadPool::DelegateSimpleThreadPool(
79     const std::string& name_prefix,
80     int num_threads)
81     : name_prefix_(name_prefix),
82       num_threads_(num_threads),
83       dry_(true, false) {
84 }
85 
~DelegateSimpleThreadPool()86 DelegateSimpleThreadPool::~DelegateSimpleThreadPool() {
87   DCHECK(threads_.empty());
88   DCHECK(delegates_.empty());
89   DCHECK(!dry_.IsSignaled());
90 }
91 
Start()92 void DelegateSimpleThreadPool::Start() {
93   DCHECK(threads_.empty()) << "Start() called with outstanding threads.";
94   for (int i = 0; i < num_threads_; ++i) {
95     DelegateSimpleThread* thread = new DelegateSimpleThread(this, name_prefix_);
96     thread->Start();
97     threads_.push_back(thread);
98   }
99 }
100 
JoinAll()101 void DelegateSimpleThreadPool::JoinAll() {
102   DCHECK(!threads_.empty()) << "JoinAll() called with no outstanding threads.";
103 
104   // Tell all our threads to quit their worker loop.
105   AddWork(NULL, num_threads_);
106 
107   // Join and destroy all the worker threads.
108   for (int i = 0; i < num_threads_; ++i) {
109     threads_[i]->Join();
110     delete threads_[i];
111   }
112   threads_.clear();
113   DCHECK(delegates_.empty());
114 }
115 
AddWork(Delegate * delegate,int repeat_count)116 void DelegateSimpleThreadPool::AddWork(Delegate* delegate, int repeat_count) {
117   AutoLock locked(lock_);
118   for (int i = 0; i < repeat_count; ++i)
119     delegates_.push(delegate);
120   // If we were empty, signal that we have work now.
121   if (!dry_.IsSignaled())
122     dry_.Signal();
123 }
124 
Run()125 void DelegateSimpleThreadPool::Run() {
126   Delegate* work = NULL;
127 
128   while (true) {
129     dry_.Wait();
130     {
131       AutoLock locked(lock_);
132       if (!dry_.IsSignaled())
133         continue;
134 
135       DCHECK(!delegates_.empty());
136       work = delegates_.front();
137       delegates_.pop();
138 
139       // Signal to any other threads that we're currently out of work.
140       if (delegates_.empty())
141         dry_.Reset();
142     }
143 
144     // A NULL delegate pointer signals us to quit.
145     if (!work)
146       break;
147 
148     work->Run();
149   }
150 }
151 
152 }  // namespace base
153