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

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
« no previous file with comments | « base/threading/thread.h ('k') | chrome_frame/buggy_bho_handling.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 14 matching lines...) Expand all
38 42
39 // Used to synchronize thread startup. 43 // Used to synchronize thread startup.
40 WaitableEvent event; 44 WaitableEvent event;
41 45
42 explicit StartupData(const Options& opt) 46 explicit StartupData(const Options& opt)
43 : options(opt), 47 : options(opt),
44 event(false, false) {} 48 event(false, false) {}
45 }; 49 };
46 50
47 Thread::Thread(const char* name) 51 Thread::Thread(const char* name)
48 : started_(false), 52 :
53 #if defined(OS_WIN)
54 com_status_(NONE),
55 #endif
56 started_(false),
49 stopping_(false), 57 stopping_(false),
50 running_(false), 58 running_(false),
51 startup_data_(NULL), 59 startup_data_(NULL),
52 thread_(0), 60 thread_(0),
53 message_loop_(NULL), 61 message_loop_(NULL),
54 thread_id_(kInvalidThreadId), 62 thread_id_(kInvalidThreadId),
55 name_(name) { 63 name_(name) {
56 } 64 }
57 65
58 Thread::~Thread() { 66 Thread::~Thread() {
59 Stop(); 67 Stop();
60 } 68 }
61 69
62 bool Thread::Start() { 70 bool Thread::Start() {
63 return StartWithOptions(Options()); 71 Options options;
72 #if defined(OS_WIN)
73 if (com_status_ == STA)
74 options.message_loop_type = MessageLoop::TYPE_UI;
75 #endif
76 return StartWithOptions(options);
64 } 77 }
65 78
66 bool Thread::StartWithOptions(const Options& options) { 79 bool Thread::StartWithOptions(const Options& options) {
67 DCHECK(!message_loop_); 80 DCHECK(!message_loop_);
81 #if defined(OS_WIN)
82 DCHECK((com_status_ != STA) ||
83 (options.message_loop_type == MessageLoop::TYPE_UI));
84 #endif
68 85
69 SetThreadWasQuitProperly(false); 86 SetThreadWasQuitProperly(false);
70 87
71 StartupData startup_data(options); 88 StartupData startup_data(options);
72 startup_data_ = &startup_data; 89 startup_data_ = &startup_data;
73 90
74 if (!PlatformThread::Create(options.stack_size, this, &thread_)) { 91 if (!PlatformThread::Create(options.stack_size, this, &thread_)) {
75 DLOG(ERROR) << "failed to create thread"; 92 DLOG(ERROR) << "failed to create thread";
76 startup_data_ = NULL; 93 startup_data_ = NULL;
77 return false; 94 return false;
78 } 95 }
79 96
80 // Wait for the thread to start and initialize message_loop_ 97 // Wait for the thread to start and initialize message_loop_
81 base::ThreadRestrictions::ScopedAllowWait allow_wait; 98 base::ThreadRestrictions::ScopedAllowWait allow_wait;
82 startup_data.event.Wait(); 99 startup_data.event.Wait();
83 100
84 // set it to NULL so we don't keep a pointer to some object on the stack. 101 // set it to NULL so we don't keep a pointer to some object on the stack.
85 startup_data_ = NULL; 102 startup_data_ = NULL;
86 started_ = true; 103 started_ = true;
87 104
88 DCHECK(message_loop_); 105 DCHECK(message_loop_);
89 return true; 106 return true;
90 } 107 }
91 108
92 void Thread::Stop() { 109 void Thread::Stop() {
93 if (!thread_was_started()) 110 if (!started_)
94 return; 111 return;
95 112
96 StopSoon(); 113 StopSoon();
97 114
98 // Wait for the thread to exit. 115 // Wait for the thread to exit.
99 // 116 //
100 // TODO(darin): Unfortunately, we need to keep message_loop_ around until 117 // TODO(darin): Unfortunately, we need to keep message_loop_ around until
101 // the thread exits. Some consumers are abusing the API. Make them stop. 118 // the thread exits. Some consumers are abusing the API. Make them stop.
102 // 119 //
103 PlatformThread::Join(thread_); 120 PlatformThread::Join(thread_);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // The message loop for this thread. 167 // The message loop for this thread.
151 MessageLoop message_loop(startup_data_->options.message_loop_type); 168 MessageLoop message_loop(startup_data_->options.message_loop_type);
152 169
153 // Complete the initialization of our Thread object. 170 // Complete the initialization of our Thread object.
154 thread_id_ = PlatformThread::CurrentId(); 171 thread_id_ = PlatformThread::CurrentId();
155 PlatformThread::SetName(name_.c_str()); 172 PlatformThread::SetName(name_.c_str());
156 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. 173 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector.
157 message_loop.set_thread_name(name_); 174 message_loop.set_thread_name(name_);
158 message_loop_ = &message_loop; 175 message_loop_ = &message_loop;
159 176
177 #if defined(OS_WIN)
178 scoped_ptr<win::ScopedCOMInitializer> com_initializer;
179 if (com_status_ != NONE) {
180 com_initializer.reset((com_status_ == STA) ?
181 new win::ScopedCOMInitializer() :
182 new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
183 }
184 #endif
185
160 // Let the thread do extra initialization. 186 // Let the thread do extra initialization.
161 // Let's do this before signaling we are started. 187 // Let's do this before signaling we are started.
162 Init(); 188 Init();
163 189
164 running_ = true; 190 running_ = true;
165 startup_data_->event.Signal(); 191 startup_data_->event.Signal();
166 // startup_data_ can't be touched anymore since the starting thread is now 192 // startup_data_ can't be touched anymore since the starting thread is now
167 // unlocked. 193 // unlocked.
168 194
169 Run(message_loop_); 195 Run(message_loop_);
170 running_ = false; 196 running_ = false;
171 197
172 // Let the thread do extra cleanup. 198 // Let the thread do extra cleanup.
173 CleanUp(); 199 CleanUp();
174 200
201 #if defined(OS_WIN)
202 com_initializer.reset();
203 #endif
204
175 // Assert that MessageLoop::Quit was called by ThreadQuitHelper. 205 // Assert that MessageLoop::Quit was called by ThreadQuitHelper.
176 DCHECK(GetThreadWasQuitProperly()); 206 DCHECK(GetThreadWasQuitProperly());
177 207
178 // We can't receive messages anymore. 208 // We can't receive messages anymore.
179 message_loop_ = NULL; 209 message_loop_ = NULL;
180 } 210 }
181 } 211 }
182 212
183 } // namespace base 213 } // namespace base
OLDNEW
« no previous file with comments | « base/threading/thread.h ('k') | chrome_frame/buggy_bho_handling.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698