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 "remoting/base/auto_thread.h" | 5 #include "remoting/base/auto_thread.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" |
8 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" |
9 #include "base/run_loop.h" | 11 #include "base/run_loop.h" |
10 #include "base/synchronization/waitable_event.h" | 12 #include "base/synchronization/waitable_event.h" |
11 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" | 13 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" |
12 #include "base/threading/thread_local.h" | 14 #include "base/threading/thread_local.h" |
13 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
14 #include "build/build_config.h" | 16 #include "build/build_config.h" |
15 #include "remoting/base/auto_thread_task_runner.h" | 17 #include "remoting/base/auto_thread_task_runner.h" |
16 | 18 |
17 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
18 #include "base/win/scoped_com_initializer.h" | 20 #include "base/win/scoped_com_initializer.h" |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 #endif | 94 #endif |
93 | 95 |
94 AutoThread::AutoThread(const char* name) | 96 AutoThread::AutoThread(const char* name) |
95 : startup_data_(NULL), | 97 : startup_data_(NULL), |
96 #if defined(OS_WIN) | 98 #if defined(OS_WIN) |
97 com_init_type_(COM_INIT_NONE), | 99 com_init_type_(COM_INIT_NONE), |
98 #endif | 100 #endif |
99 thread_(), | 101 thread_(), |
100 name_(name), | 102 name_(name), |
101 was_quit_properly_(false) { | 103 was_quit_properly_(false) { |
| 104 thread_checker_.DetachFromThread(); |
102 } | 105 } |
103 | 106 |
104 AutoThread::AutoThread(const char* name, AutoThreadTaskRunner* joiner) | 107 AutoThread::AutoThread(const char* name, AutoThreadTaskRunner* joiner) |
105 : startup_data_(NULL), | 108 : startup_data_(NULL), |
106 #if defined(OS_WIN) | 109 #if defined(OS_WIN) |
107 com_init_type_(COM_INIT_NONE), | 110 com_init_type_(COM_INIT_NONE), |
108 #endif | 111 #endif |
109 thread_(), | 112 thread_(), |
110 name_(name), | 113 name_(name), |
111 was_quit_properly_(false), | 114 was_quit_properly_(false), |
112 joiner_(joiner) { | 115 joiner_(joiner) { |
| 116 thread_checker_.DetachFromThread(); |
113 } | 117 } |
114 | 118 |
115 AutoThread::~AutoThread() { | 119 AutoThread::~AutoThread() { |
116 DCHECK(!startup_data_); | 120 DCHECK(!startup_data_); |
117 | 121 |
118 // Wait for the thread to exit. | 122 // Wait for the thread to exit. |
119 if (!thread_.is_null()) { | 123 if (!thread_.is_null()) { |
120 base::PlatformThread::Join(thread_); | 124 base::PlatformThread::Join(thread_); |
121 } | 125 } |
122 } | 126 } |
(...skipping 29 matching lines...) Expand all Loading... |
152 return startup_data.task_runner; | 156 return startup_data.task_runner; |
153 } | 157 } |
154 | 158 |
155 #if defined(OS_WIN) | 159 #if defined(OS_WIN) |
156 void AutoThread::SetComInitType(ComInitType com_init_type) { | 160 void AutoThread::SetComInitType(ComInitType com_init_type) { |
157 DCHECK_EQ(com_init_type_, COM_INIT_NONE); | 161 DCHECK_EQ(com_init_type_, COM_INIT_NONE); |
158 com_init_type_ = com_init_type; | 162 com_init_type_ = com_init_type; |
159 } | 163 } |
160 #endif | 164 #endif |
161 | 165 |
162 void AutoThread::QuitThread( | 166 void AutoThread::QuitThread(const base::Closure& quit_when_idle_closure) { |
163 scoped_refptr<base::SingleThreadTaskRunner> task_runner) { | 167 DCHECK(thread_checker_.CalledOnValidThread()); |
164 if (!task_runner->BelongsToCurrentThread()) { | |
165 task_runner->PostTask(FROM_HERE, base::Bind(&AutoThread::QuitThread, | |
166 base::Unretained(this), | |
167 task_runner)); | |
168 return; | |
169 } | |
170 | 168 |
171 base::MessageLoop::current()->QuitWhenIdle(); | 169 quit_when_idle_closure.Run(); |
172 was_quit_properly_ = true; | 170 was_quit_properly_ = true; |
173 | 171 |
174 if (joiner_.get()) { | 172 if (joiner_.get()) { |
175 joiner_->PostTask( | 173 joiner_->PostTask( |
176 FROM_HERE, | 174 FROM_HERE, |
177 base::Bind(&AutoThread::JoinAndDeleteThread, base::Unretained(this))); | 175 base::Bind(&AutoThread::JoinAndDeleteThread, base::Unretained(this))); |
178 } | 176 } |
179 } | 177 } |
180 | 178 |
181 void AutoThread::JoinAndDeleteThread() { | 179 void AutoThread::JoinAndDeleteThread() { |
182 delete this; | 180 delete this; |
183 } | 181 } |
184 | 182 |
185 void AutoThread::ThreadMain() { | 183 void AutoThread::ThreadMain() { |
186 // The message loop for this thread. | 184 // Bind |thread_checker_| to the current thread. |
| 185 DCHECK(thread_checker_.CalledOnValidThread()); |
| 186 |
187 base::MessageLoop message_loop(startup_data_->loop_type); | 187 base::MessageLoop message_loop(startup_data_->loop_type); |
| 188 base::RunLoop run_loop; |
188 | 189 |
189 // Complete the initialization of our AutoThread object. | 190 // Complete the initialization of our AutoThread object. |
190 base::PlatformThread::SetName(name_); | 191 base::PlatformThread::SetName(name_); |
191 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. | 192 ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. |
192 | 193 |
193 // Return an AutoThreadTaskRunner that will cleanly quit this thread when | 194 // Return an AutoThreadTaskRunner that will cleanly quit this thread when |
194 // no more references to it remain. | 195 // no more references to it remain. |
195 startup_data_->task_runner = | 196 startup_data_->task_runner = new AutoThreadTaskRunner( |
196 new AutoThreadTaskRunner(message_loop.task_runner(), | 197 message_loop.task_runner(), |
197 base::Bind(&AutoThread::QuitThread, | 198 base::Bind(&AutoThread::QuitThread, base::Unretained(this), |
198 base::Unretained(this), | 199 run_loop.QuitWhenIdleClosure())); |
199 message_loop.task_runner())); | |
200 | 200 |
201 startup_data_->event.Signal(); | 201 startup_data_->event.Signal(); |
202 // startup_data_ can't be touched anymore since the starting thread is now | 202 // startup_data_ can't be touched anymore since the starting thread is now |
203 // unlocked. | 203 // unlocked. |
204 | 204 |
205 #if defined(OS_WIN) | 205 #if defined(OS_WIN) |
206 // Initialize COM on the thread, if requested. | 206 // Initialize COM on the thread, if requested. |
207 std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer( | 207 std::unique_ptr<base::win::ScopedCOMInitializer> com_initializer( |
208 CreateComInitializer(com_init_type_)); | 208 CreateComInitializer(com_init_type_)); |
209 #endif | 209 #endif |
210 | 210 |
211 base::RunLoop().Run(); | 211 run_loop.Run(); |
212 | 212 |
213 // Assert that MessageLoop::QuitWhenIdle was called by AutoThread::QuitThread. | 213 // Assert that MessageLoop::QuitWhenIdle was called by AutoThread::QuitThread. |
214 DCHECK(was_quit_properly_); | 214 DCHECK(was_quit_properly_); |
215 } | 215 } |
216 | 216 |
217 } // namespace base | 217 } // namespace base |
OLD | NEW |