OLD | NEW |
| (Empty) |
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/simple_thread.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/platform_thread.h" | |
9 #include "base/string_number_conversions.h" | |
10 | |
11 namespace base { | |
12 | |
13 void SimpleThread::Start() { | |
14 DCHECK(!HasBeenStarted()) << "Tried to Start a thread multiple times."; | |
15 bool success = PlatformThread::Create(options_.stack_size(), this, &thread_); | |
16 CHECK(success); | |
17 event_.Wait(); // Wait for the thread to complete initialization. | |
18 } | |
19 | |
20 void SimpleThread::Join() { | |
21 DCHECK(HasBeenStarted()) << "Tried to Join a never-started thread."; | |
22 DCHECK(!HasBeenJoined()) << "Tried to Join a thread multiple times."; | |
23 PlatformThread::Join(thread_); | |
24 joined_ = true; | |
25 } | |
26 | |
27 void SimpleThread::ThreadMain() { | |
28 tid_ = PlatformThread::CurrentId(); | |
29 // Construct our full name of the form "name_prefix_/TID". | |
30 name_.push_back('/'); | |
31 name_.append(IntToString(tid_)); | |
32 PlatformThread::SetName(name_.c_str()); | |
33 | |
34 // We've initialized our new thread, signal that we're done to Start(). | |
35 event_.Signal(); | |
36 | |
37 Run(); | |
38 } | |
39 | |
40 SimpleThread::SimpleThread(const std::string& name_prefix) | |
41 : name_prefix_(name_prefix), name_(name_prefix), | |
42 thread_(), event_(true, false), tid_(0), joined_(false) { | |
43 } | |
44 | |
45 SimpleThread::SimpleThread(const std::string& name_prefix, | |
46 const Options& options) | |
47 : name_prefix_(name_prefix), name_(name_prefix), options_(options), | |
48 thread_(), event_(true, false), tid_(0), joined_(false) { | |
49 } | |
50 | |
51 SimpleThread::~SimpleThread() { | |
52 DCHECK(HasBeenStarted()) << "SimpleThread was never started."; | |
53 DCHECK(HasBeenJoined()) << "SimpleThread destroyed without being Join()ed."; | |
54 } | |
55 | |
56 DelegateSimpleThread::DelegateSimpleThread(Delegate* delegate, | |
57 const std::string& name_prefix) | |
58 : SimpleThread(name_prefix), | |
59 delegate_(delegate) { | |
60 } | |
61 | |
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 | |
69 DelegateSimpleThread::~DelegateSimpleThread() { | |
70 } | |
71 | |
72 void DelegateSimpleThread::Run() { | |
73 DCHECK(delegate_) << "Tried to call Run without a delegate (called twice?)"; | |
74 delegate_->Run(); | |
75 delegate_ = NULL; | |
76 } | |
77 | |
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 | |
86 DelegateSimpleThreadPool::~DelegateSimpleThreadPool() { | |
87 DCHECK(threads_.empty()); | |
88 DCHECK(delegates_.empty()); | |
89 DCHECK(!dry_.IsSignaled()); | |
90 } | |
91 | |
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 | |
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 | |
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 | |
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 | |
OLD | NEW |