Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(285)

Side by Side Diff: base/threading/thread.cc

Issue 11048029: Allow Thread to initialize COM for Windows consumers who need it (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/third_party/dynamic_annotations/dynamic_annotations.h" 9 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
10 #include "base/threading/thread_local.h" 10 #include "base/threading/thread_local.h"
11 #include "base/threading/thread_restrictions.h" 11 #include "base/threading/thread_restrictions.h"
12 #include "base/synchronization/waitable_event.h" 12 #include "base/synchronization/waitable_event.h"
13 13
14 #if defined(OS_WIN)
15 #include "base/win/scoped_com_initializer.h"
16 #endif
17
14 namespace base { 18 namespace base {
15 19
16 namespace { 20 namespace {
17 21
18 // We use this thread-local variable to record whether or not a thread exited 22 // We use this thread-local variable to record whether or not a thread exited
19 // because its Stop method was called. This allows us to catch cases where 23 // because its Stop method was called. This allows us to catch cases where
20 // MessageLoop::Quit() is called directly, which is unexpected when using a 24 // MessageLoop::Quit() is called directly, which is unexpected when using a
21 // Thread to setup and run a MessageLoop. 25 // Thread to setup and run a MessageLoop.
22 base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool = 26 base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool =
23 LAZY_INSTANCE_INITIALIZER; 27 LAZY_INSTANCE_INITIALIZER;
(...skipping 29 matching lines...) Expand all
53 message_loop_(NULL), 57 message_loop_(NULL),
54 thread_id_(kInvalidThreadId), 58 thread_id_(kInvalidThreadId),
55 name_(name) { 59 name_(name) {
56 } 60 }
57 61
58 Thread::~Thread() { 62 Thread::~Thread() {
59 Stop(); 63 Stop();
60 } 64 }
61 65
62 bool Thread::Start() { 66 bool Thread::Start() {
63 return StartWithOptions(Options()); 67 Options options;
68 #if defined(OS_WIN)
69 if (com_status_ == STA)
70 options.message_loop_type = MessageLoop::TYPE_UI;
71 #endif
72 return StartWithOptions(options);
64 } 73 }
65 74
66 bool Thread::StartWithOptions(const Options& options) { 75 bool Thread::StartWithOptions(const Options& options) {
67 DCHECK(!message_loop_); 76 DCHECK(!message_loop_);
77 #if defined(OS_WIN)
78 DCHECK((com_status_ != STA) ||
79 (options.message_loop_type == MessageLoop::TYPE_UI));
80 #endif
68 81
69 SetThreadWasQuitProperly(false); 82 SetThreadWasQuitProperly(false);
70 83
71 StartupData startup_data(options); 84 StartupData startup_data(options);
72 startup_data_ = &startup_data; 85 startup_data_ = &startup_data;
73 86
74 if (!PlatformThread::Create(options.stack_size, this, &thread_)) { 87 if (!PlatformThread::Create(options.stack_size, this, &thread_)) {
75 DLOG(ERROR) << "failed to create thread"; 88 DLOG(ERROR) << "failed to create thread";
76 startup_data_ = NULL; 89 startup_data_ = NULL;
77 return false; 90 return false;
78 } 91 }
79 92
80 // Wait for the thread to start and initialize message_loop_ 93 // Wait for the thread to start and initialize message_loop_
81 base::ThreadRestrictions::ScopedAllowWait allow_wait; 94 base::ThreadRestrictions::ScopedAllowWait allow_wait;
82 startup_data.event.Wait(); 95 startup_data.event.Wait();
83 96
84 // set it to NULL so we don't keep a pointer to some object on the stack. 97 // set it to NULL so we don't keep a pointer to some object on the stack.
85 startup_data_ = NULL; 98 startup_data_ = NULL;
86 started_ = true; 99 started_ = true;
87 100
88 DCHECK(message_loop_); 101 DCHECK(message_loop_);
89 return true; 102 return true;
90 } 103 }
91 104
92 void Thread::Stop() { 105 void Thread::Stop() {
93 if (!thread_was_started()) 106 if (!started_)
94 return; 107 return;
95 108
96 StopSoon(); 109 StopSoon();
97 110
98 // Wait for the thread to exit. 111 // Wait for the thread to exit.
99 // 112 //
100 // TODO(darin): Unfortunately, we need to keep message_loop_ around until 113 // TODO(darin): Unfortunately, we need to keep message_loop_ around until
101 // the thread exits. Some consumers are abusing the API. Make them stop. 114 // the thread exits. Some consumers are abusing the API. Make them stop.
102 // 115 //
103 PlatformThread::Join(thread_); 116 PlatformThread::Join(thread_);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // The message loop for this thread. 163 // The message loop for this thread.
151 MessageLoop message_loop(startup_data_->options.message_loop_type); 164 MessageLoop message_loop(startup_data_->options.message_loop_type);
152 165
153 // Complete the initialization of our Thread object. 166 // Complete the initialization of our Thread object.
154 thread_id_ = PlatformThread::CurrentId(); 167 thread_id_ = PlatformThread::CurrentId();
155 PlatformThread::SetName(name_.c_str()); 168 PlatformThread::SetName(name_.c_str());
156 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. 169 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector.
157 message_loop.set_thread_name(name_); 170 message_loop.set_thread_name(name_);
158 message_loop_ = &message_loop; 171 message_loop_ = &message_loop;
159 172
173 #if defined(OS_WIN)
174 if (com_status_ != NONE) {
175 com_initializer_.reset((com_status_ == STA) ?
176 new win::ScopedCOMInitializer() :
177 new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
178 }
179 #endif
180
160 // Let the thread do extra initialization. 181 // Let the thread do extra initialization.
161 // Let's do this before signaling we are started. 182 // Let's do this before signaling we are started.
162 Init(); 183 Init();
163 184
164 running_ = true; 185 running_ = true;
165 startup_data_->event.Signal(); 186 startup_data_->event.Signal();
166 // startup_data_ can't be touched anymore since the starting thread is now 187 // startup_data_ can't be touched anymore since the starting thread is now
167 // unlocked. 188 // unlocked.
168 189
169 Run(message_loop_); 190 Run(message_loop_);
170 running_ = false; 191 running_ = false;
171 192
172 // Let the thread do extra cleanup. 193 // Let the thread do extra cleanup.
173 CleanUp(); 194 CleanUp();
174 195
196 #if defined(OS_WIN)
197 com_initializer_.reset();
Ami GONE FROM CHROMIUM 2012/10/16 02:52:03 observation: this variable is only used in this fu
198 #endif
199
175 // Assert that MessageLoop::Quit was called by ThreadQuitHelper. 200 // Assert that MessageLoop::Quit was called by ThreadQuitHelper.
176 DCHECK(GetThreadWasQuitProperly()); 201 DCHECK(GetThreadWasQuitProperly());
177 202
178 // We can't receive messages anymore. 203 // We can't receive messages anymore.
179 message_loop_ = NULL; 204 message_loop_ = NULL;
180 } 205 }
181 } 206 }
182 207
183 } // namespace base 208 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698