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 "base/threading/thread.h" | 5 #include "base/threading/thread.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/lazy_instance.h" | 8 #include "base/lazy_instance.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
12 #include "base/threading/thread_id_name_manager.h" | 12 #include "base/threading/thread_id_name_manager.h" |
13 #include "base/threading/thread_local.h" | 13 #include "base/threading/thread_local.h" |
14 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
15 | 15 |
16 #if defined(OS_WIN) | |
17 #include "base/win/scoped_com_initializer.h" | |
18 #endif | |
19 | |
20 namespace base { | 16 namespace base { |
21 | 17 |
22 namespace { | 18 namespace { |
23 | 19 |
24 // We use this thread-local variable to record whether or not a thread exited | 20 // We use this thread-local variable to record whether or not a thread exited |
25 // because its Stop method was called. This allows us to catch cases where | 21 // because its Stop method was called. This allows us to catch cases where |
26 // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when | 22 // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when |
27 // using a Thread to setup and run a MessageLoop. | 23 // using a Thread to setup and run a MessageLoop. |
28 base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool = | 24 base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool = |
29 LAZY_INSTANCE_INITIALIZER; | 25 LAZY_INSTANCE_INITIALIZER; |
(...skipping 19 matching lines...) Expand all Loading... |
49 timer_slack(TIMER_SLACK_NONE), | 45 timer_slack(TIMER_SLACK_NONE), |
50 stack_size(size), | 46 stack_size(size), |
51 priority(ThreadPriority::NORMAL) { | 47 priority(ThreadPriority::NORMAL) { |
52 } | 48 } |
53 | 49 |
54 Thread::Options::~Options() { | 50 Thread::Options::~Options() { |
55 } | 51 } |
56 | 52 |
57 Thread::Thread(const std::string& name) | 53 Thread::Thread(const std::string& name) |
58 : | 54 : |
59 #if defined(OS_WIN) | |
60 com_status_(NONE), | |
61 #endif | |
62 stopping_(false), | 55 stopping_(false), |
63 running_(false), | 56 running_(false), |
64 thread_(0), | 57 thread_(0), |
65 message_loop_(nullptr), | 58 message_loop_(nullptr), |
66 message_loop_timer_slack_(TIMER_SLACK_NONE), | 59 message_loop_timer_slack_(TIMER_SLACK_NONE), |
67 name_(name) { | 60 name_(name) { |
68 } | 61 } |
69 | 62 |
70 Thread::~Thread() { | 63 Thread::~Thread() { |
71 Stop(); | 64 Stop(); |
72 } | 65 } |
73 | 66 |
74 bool Thread::Start() { | 67 bool Thread::Start() { |
75 Options options; | 68 Options options; |
76 #if defined(OS_WIN) | |
77 if (com_status_ == STA) | |
78 options.message_loop_type = MessageLoop::TYPE_UI; | |
79 #endif | |
80 return StartWithOptions(options); | 69 return StartWithOptions(options); |
81 } | 70 } |
82 | 71 |
83 bool Thread::StartWithOptions(const Options& options) { | 72 bool Thread::StartWithOptions(const Options& options) { |
84 DCHECK(!message_loop_); | 73 DCHECK(!message_loop_); |
85 #if defined(OS_WIN) | |
86 DCHECK((com_status_ != STA) || | |
87 (options.message_loop_type == MessageLoop::TYPE_UI)); | |
88 #endif | |
89 | |
90 SetThreadWasQuitProperly(false); | 74 SetThreadWasQuitProperly(false); |
91 | 75 |
92 MessageLoop::Type type = options.message_loop_type; | 76 MessageLoop::Type type = options.message_loop_type; |
93 if (!options.message_pump_factory.is_null()) | 77 if (!options.message_pump_factory.is_null()) |
94 type = MessageLoop::TYPE_CUSTOM; | 78 type = MessageLoop::TYPE_CUSTOM; |
95 | 79 |
96 message_loop_timer_slack_ = options.timer_slack; | 80 message_loop_timer_slack_ = options.timer_slack; |
97 message_loop_ = new MessageLoop(type, options.message_pump_factory); | 81 message_loop_ = new MessageLoop(type, options.message_pump_factory); |
98 | 82 |
99 start_event_.reset(new WaitableEvent(false, false)); | 83 start_event_.reset(new WaitableEvent(false, false)); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 PlatformThread::SetName(name_.c_str()); | 202 PlatformThread::SetName(name_.c_str()); |
219 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. | 203 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. |
220 | 204 |
221 // Lazily initialize the message_loop so that it can run on this thread. | 205 // Lazily initialize the message_loop so that it can run on this thread. |
222 DCHECK(message_loop_); | 206 DCHECK(message_loop_); |
223 scoped_ptr<MessageLoop> message_loop(message_loop_); | 207 scoped_ptr<MessageLoop> message_loop(message_loop_); |
224 message_loop_->BindToCurrentThread(); | 208 message_loop_->BindToCurrentThread(); |
225 message_loop_->set_thread_name(name_); | 209 message_loop_->set_thread_name(name_); |
226 message_loop_->SetTimerSlack(message_loop_timer_slack_); | 210 message_loop_->SetTimerSlack(message_loop_timer_slack_); |
227 | 211 |
228 #if defined(OS_WIN) | |
229 scoped_ptr<win::ScopedCOMInitializer> com_initializer; | |
230 if (com_status_ != NONE) { | |
231 com_initializer.reset((com_status_ == STA) ? | |
232 new win::ScopedCOMInitializer() : | |
233 new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA)); | |
234 } | |
235 #endif | |
236 | |
237 // Make sure the thread_id() returns current thread. | 212 // Make sure the thread_id() returns current thread. |
238 // (This internally acquires lock against PlatformThread::Create) | 213 // (This internally acquires lock against PlatformThread::Create) |
239 DCHECK_EQ(thread_id(), PlatformThread::CurrentId()); | 214 DCHECK_EQ(thread_id(), PlatformThread::CurrentId()); |
240 | 215 |
241 // Let the thread do extra initialization. | 216 // Let the thread do extra initialization. |
242 Init(); | 217 Init(); |
243 | 218 |
244 { | 219 { |
245 AutoLock lock(running_lock_); | 220 AutoLock lock(running_lock_); |
246 running_ = true; | 221 running_ = true; |
247 } | 222 } |
248 | 223 |
249 start_event_->Signal(); | 224 start_event_->Signal(); |
250 | 225 |
251 Run(message_loop_); | 226 Run(message_loop_); |
252 | 227 |
253 { | 228 { |
254 AutoLock lock(running_lock_); | 229 AutoLock lock(running_lock_); |
255 running_ = false; | 230 running_ = false; |
256 } | 231 } |
257 | 232 |
258 // Let the thread do extra cleanup. | 233 // Let the thread do extra cleanup. |
259 CleanUp(); | 234 CleanUp(); |
260 | 235 |
261 #if defined(OS_WIN) | |
262 com_initializer.reset(); | |
263 #endif | |
264 | |
265 // Assert that MessageLoop::Quit was called by ThreadQuitHelper. | 236 // Assert that MessageLoop::Quit was called by ThreadQuitHelper. |
266 DCHECK(GetThreadWasQuitProperly()); | 237 DCHECK(GetThreadWasQuitProperly()); |
267 | 238 |
268 // We can't receive messages anymore. | 239 // We can't receive messages anymore. |
269 // (The message loop is destructed at the end of this block) | 240 // (The message loop is destructed at the end of this block) |
270 message_loop_ = NULL; | 241 message_loop_ = NULL; |
271 } | 242 } |
272 | 243 |
273 } // namespace base | 244 } // namespace base |
OLD | NEW |