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

Side by Side Diff: content/browser/browser_thread_impl.cc

Issue 8340028: Salient parts of http://codereview.chromium.org/8392042/ (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 9 years, 1 month 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
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/browser/browser_thread_unittest.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) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "content/browser/browser_thread.h" 5 #include "content/browser/browser_thread_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/message_loop_proxy.h" 9 #include "base/message_loop_proxy.h"
10 #include "base/threading/thread_restrictions.h" 10 #include "base/threading/thread_restrictions.h"
11 11
12 namespace {
13
12 // Friendly names for the well-known threads. 14 // Friendly names for the well-known threads.
13 static const char* browser_thread_names[BrowserThread::ID_COUNT] = { 15 static const char* browser_thread_names[BrowserThread::ID_COUNT] = {
14 "", // UI (name assembled in browser_main.cc). 16 "", // UI (name assembled in browser_main.cc).
15 "Chrome_DBThread", // DB 17 "Chrome_DBThread", // DB
16 "Chrome_WebKitThread", // WEBKIT 18 "Chrome_WebKitThread", // WEBKIT
17 "Chrome_FileThread", // FILE 19 "Chrome_FileThread", // FILE
18 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER 20 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER
19 "Chrome_CacheThread", // CACHE 21 "Chrome_CacheThread", // CACHE
20 "Chrome_IOThread", // IO 22 "Chrome_IOThread", // IO
21 #if defined(OS_CHROMEOS) 23 #if defined(OS_CHROMEOS)
22 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY 24 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY
23 #endif 25 #endif
24 }; 26 };
25 27
28 } // namespace
29
30 namespace content {
31
32 base::Lock BrowserThreadImpl::lock_;
33
34 BrowserThread* BrowserThreadImpl::browser_threads_[ID_COUNT];
35
36 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier)
37 : BrowserThread(identifier) {
38 }
39
40 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier,
41 MessageLoop* message_loop)
42 : BrowserThread(identifier, message_loop) {
43 }
44
45 BrowserThreadImpl::~BrowserThreadImpl() {
46 }
47
48 // static
49 bool BrowserThreadImpl::PostTaskHelper(
50 BrowserThread::ID identifier,
51 const tracked_objects::Location& from_here,
52 Task* task,
53 int64 delay_ms,
54 bool nestable) {
55 DCHECK(identifier >= 0 && identifier < ID_COUNT);
56 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
57 // order of lifetime. So no need to lock if we know that the other thread
58 // outlives this one.
59 // Note: since the array is so small, ok to loop instead of creating a map,
60 // which would require a lock because std::map isn't thread safe, defeating
61 // the whole purpose of this optimization.
62 BrowserThread::ID current_thread;
63 bool guaranteed_to_outlive_target_thread =
64 GetCurrentThreadIdentifier(&current_thread) &&
65 current_thread >= identifier;
66
67 if (!guaranteed_to_outlive_target_thread)
68 BrowserThreadImpl::lock_.Acquire();
69
70 MessageLoop* message_loop = BrowserThreadImpl::browser_threads_[identifier] ?
71 BrowserThreadImpl::browser_threads_[identifier]->message_loop() : NULL;
72 if (message_loop) {
73 if (nestable) {
74 message_loop->PostDelayedTask(from_here, task, delay_ms);
75 } else {
76 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
77 }
78 }
79
80 if (!guaranteed_to_outlive_target_thread)
81 BrowserThreadImpl::lock_.Release();
82
83 if (!message_loop)
84 delete task;
85
86 return !!message_loop;
87 }
88
89 // static
90 bool BrowserThreadImpl::PostTaskHelper(
91 BrowserThread::ID identifier,
92 const tracked_objects::Location& from_here,
93 const base::Closure& task,
94 int64 delay_ms,
95 bool nestable) {
96 DCHECK(identifier >= 0 && identifier < ID_COUNT);
97 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
98 // order of lifetime. So no need to lock if we know that the other thread
99 // outlives this one.
100 // Note: since the array is so small, ok to loop instead of creating a map,
101 // which would require a lock because std::map isn't thread safe, defeating
102 // the whole purpose of this optimization.
103 BrowserThread::ID current_thread;
104 bool guaranteed_to_outlive_target_thread =
105 GetCurrentThreadIdentifier(&current_thread) &&
106 current_thread >= identifier;
107
108 if (!guaranteed_to_outlive_target_thread)
109 lock_.Acquire();
110
111 MessageLoop* message_loop = browser_threads_[identifier] ?
112 browser_threads_[identifier]->message_loop() : NULL;
113 if (message_loop) {
114 if (nestable) {
115 message_loop->PostDelayedTask(from_here, task, delay_ms);
116 } else {
117 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
118 }
119 }
120
121 if (!guaranteed_to_outlive_target_thread)
122 lock_.Release();
123
124 return !!message_loop;
125 }
126
127 } // namespace content
128
129 using content::BrowserThreadImpl;
130
131 // TODO(joi): Remove
132 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier)
133 : BrowserThread(identifier) {
134 }
135 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier,
136 MessageLoop* message_loop)
137 : BrowserThread(identifier, message_loop) {
138 }
139 DeprecatedBrowserThread::~DeprecatedBrowserThread() {
140 }
141
26 // An implementation of MessageLoopProxy to be used in conjunction 142 // An implementation of MessageLoopProxy to be used in conjunction
27 // with BrowserThread. 143 // with BrowserThread.
28 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { 144 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
29 public: 145 public:
30 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) 146 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
31 : id_(identifier) { 147 : id_(identifier) {
32 } 148 }
33 149
34 // MessageLoopProxy implementation. 150 // MessageLoopProxy implementation.
35 virtual bool PostTask(const tracked_objects::Location& from_here, 151 virtual bool PostTask(const tracked_objects::Location& from_here,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 196
81 virtual bool BelongsToCurrentThread() { 197 virtual bool BelongsToCurrentThread() {
82 return BrowserThread::CurrentlyOn(id_); 198 return BrowserThread::CurrentlyOn(id_);
83 } 199 }
84 200
85 private: 201 private:
86 BrowserThread::ID id_; 202 BrowserThread::ID id_;
87 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); 203 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
88 }; 204 };
89 205
90 206 BrowserThread::BrowserThread(ID identifier)
91 base::Lock BrowserThread::lock_;
92
93 BrowserThread* BrowserThread::browser_threads_[ID_COUNT];
94
95 BrowserThread::BrowserThread(BrowserThread::ID identifier)
96 : Thread(browser_thread_names[identifier]), 207 : Thread(browser_thread_names[identifier]),
97 identifier_(identifier) { 208 identifier_(identifier) {
98 Initialize(); 209 Initialize();
99 } 210 }
100 211
101 BrowserThread::BrowserThread(ID identifier, MessageLoop* message_loop) 212 BrowserThread::BrowserThread(ID identifier,
213 MessageLoop* message_loop)
102 : Thread(message_loop->thread_name().c_str()), 214 : Thread(message_loop->thread_name().c_str()),
103 identifier_(identifier) { 215 identifier_(identifier) {
104 set_message_loop(message_loop); 216 set_message_loop(message_loop);
105 Initialize(); 217 Initialize();
106 } 218 }
107 219
108 void BrowserThread::Initialize() { 220 void BrowserThread::Initialize() {
109 base::AutoLock lock(lock_); 221 base::AutoLock lock(BrowserThreadImpl::lock_);
110 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); 222 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
111 DCHECK(browser_threads_[identifier_] == NULL); 223 DCHECK(BrowserThreadImpl::browser_threads_[identifier_] == NULL);
112 browser_threads_[identifier_] = this; 224 BrowserThreadImpl::browser_threads_[identifier_] = this;
113 } 225 }
114 226
115 BrowserThread::~BrowserThread() { 227 BrowserThread::~BrowserThread() {
116 // Stop the thread here, instead of the parent's class destructor. This is so 228 // Stop the thread here, instead of the parent's class destructor. This is so
117 // that if there are pending tasks that run, code that checks that it's on the 229 // that if there are pending tasks that run, code that checks that it's on the
118 // correct BrowserThread succeeds. 230 // correct BrowserThread succeeds.
119 Stop(); 231 Stop();
120 232
121 base::AutoLock lock(lock_); 233 base::AutoLock lock(BrowserThreadImpl::lock_);
122 browser_threads_[identifier_] = NULL; 234 BrowserThreadImpl::browser_threads_[identifier_] = NULL;
123 #ifndef NDEBUG 235 #ifndef NDEBUG
124 // Double check that the threads are ordered correctly in the enumeration. 236 // Double check that the threads are ordered correctly in the enumeration.
125 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { 237 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
126 DCHECK(!browser_threads_[i]) << 238 DCHECK(!BrowserThreadImpl::browser_threads_[i]) <<
127 "Threads must be listed in the reverse order that they die"; 239 "Threads must be listed in the reverse order that they die";
128 } 240 }
129 #endif 241 #endif
130 } 242 }
131 243
132 // static 244 // static
133 bool BrowserThread::IsWellKnownThread(ID identifier) { 245 bool BrowserThread::IsWellKnownThread(ID identifier) {
134 base::AutoLock lock(lock_); 246 base::AutoLock lock(BrowserThreadImpl::lock_);
135 return (identifier >= 0 && identifier < ID_COUNT && 247 return (identifier >= 0 && identifier < ID_COUNT &&
136 browser_threads_[identifier]); 248 BrowserThreadImpl::browser_threads_[identifier]);
137 } 249 }
138 250
139 // static 251 // static
140 bool BrowserThread::CurrentlyOn(ID identifier) { 252 bool BrowserThread::CurrentlyOn(ID identifier) {
141 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 253 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
142 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 254 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
143 // function. 255 // function.
144 // http://crbug.com/63678 256 // http://crbug.com/63678
145 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 257 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
146 base::AutoLock lock(lock_); 258 base::AutoLock lock(BrowserThreadImpl::lock_);
147 DCHECK(identifier >= 0 && identifier < ID_COUNT); 259 DCHECK(identifier >= 0 && identifier < ID_COUNT);
148 return browser_threads_[identifier] && 260 return BrowserThreadImpl::browser_threads_[identifier] &&
149 browser_threads_[identifier]->message_loop() == MessageLoop::current(); 261 BrowserThreadImpl::browser_threads_[identifier]->message_loop() ==
262 MessageLoop::current();
150 } 263 }
151 264
152 // static 265 // static
153 bool BrowserThread::IsMessageLoopValid(ID identifier) { 266 bool BrowserThread::IsMessageLoopValid(ID identifier) {
154 base::AutoLock lock(lock_); 267 base::AutoLock lock(BrowserThreadImpl::lock_);
155 DCHECK(identifier >= 0 && identifier < ID_COUNT); 268 DCHECK(identifier >= 0 && identifier < ID_COUNT);
156 return browser_threads_[identifier] && 269 return BrowserThreadImpl::browser_threads_[identifier] &&
157 browser_threads_[identifier]->message_loop(); 270 BrowserThreadImpl::browser_threads_[identifier]->message_loop();
158 } 271 }
159 272
160 // static 273 // static
161 bool BrowserThread::PostTask(ID identifier, 274 bool BrowserThread::PostTask(ID identifier,
162 const tracked_objects::Location& from_here, 275 const tracked_objects::Location& from_here,
163 const base::Closure& task) { 276 const base::Closure& task) {
164 return PostTaskHelper(identifier, from_here, task, 0, true); 277 return BrowserThreadImpl::PostTaskHelper(
278 identifier, from_here, task, 0, true);
165 } 279 }
166 280
167 // static 281 // static
168 bool BrowserThread::PostDelayedTask(ID identifier, 282 bool BrowserThread::PostDelayedTask(ID identifier,
169 const tracked_objects::Location& from_here, 283 const tracked_objects::Location& from_here,
170 const base::Closure& task, 284 const base::Closure& task,
171 int64 delay_ms) { 285 int64 delay_ms) {
172 return PostTaskHelper(identifier, from_here, task, delay_ms, true); 286 return BrowserThreadImpl::PostTaskHelper(
287 identifier, from_here, task, delay_ms, true);
173 } 288 }
174 289
175 // static 290 // static
176 bool BrowserThread::PostNonNestableTask( 291 bool BrowserThread::PostNonNestableTask(
177 ID identifier, 292 ID identifier,
178 const tracked_objects::Location& from_here, 293 const tracked_objects::Location& from_here,
179 const base::Closure& task) { 294 const base::Closure& task) {
180 return PostTaskHelper(identifier, from_here, task, 0, false); 295 return BrowserThreadImpl::PostTaskHelper(
296 identifier, from_here, task, 0, false);
181 } 297 }
182 298
183 // static 299 // static
184 bool BrowserThread::PostNonNestableDelayedTask( 300 bool BrowserThread::PostNonNestableDelayedTask(
185 ID identifier, 301 ID identifier,
186 const tracked_objects::Location& from_here, 302 const tracked_objects::Location& from_here,
187 const base::Closure& task, 303 const base::Closure& task,
188 int64 delay_ms) { 304 int64 delay_ms) {
189 return PostTaskHelper(identifier, from_here, task, delay_ms, false); 305 return BrowserThreadImpl::PostTaskHelper(
306 identifier, from_here, task, delay_ms, false);
190 } 307 }
191 308
192 // static 309 // static
193 bool BrowserThread::PostTask(ID identifier, 310 bool BrowserThread::PostTask(ID identifier,
194 const tracked_objects::Location& from_here, 311 const tracked_objects::Location& from_here,
195 Task* task) { 312 Task* task) {
196 return PostTaskHelper(identifier, from_here, task, 0, true); 313 return BrowserThreadImpl::PostTaskHelper(
314 identifier, from_here, task, 0, true);
197 } 315 }
198 316
199 // static 317 // static
200 bool BrowserThread::PostDelayedTask(ID identifier, 318 bool BrowserThread::PostDelayedTask(ID identifier,
201 const tracked_objects::Location& from_here, 319 const tracked_objects::Location& from_here,
202 Task* task, 320 Task* task,
203 int64 delay_ms) { 321 int64 delay_ms) {
204 return PostTaskHelper(identifier, from_here, task, delay_ms, true); 322 return BrowserThreadImpl::PostTaskHelper(
323 identifier, from_here, task, delay_ms, true);
205 } 324 }
206 325
207 // static 326 // static
208 bool BrowserThread::PostNonNestableTask( 327 bool BrowserThread::PostNonNestableTask(
209 ID identifier, 328 ID identifier,
210 const tracked_objects::Location& from_here, 329 const tracked_objects::Location& from_here,
211 Task* task) { 330 Task* task) {
212 return PostTaskHelper(identifier, from_here, task, 0, false); 331 return BrowserThreadImpl::PostTaskHelper(
332 identifier, from_here, task, 0, false);
213 } 333 }
214 334
215 // static 335 // static
216 bool BrowserThread::PostNonNestableDelayedTask( 336 bool BrowserThread::PostNonNestableDelayedTask(
217 ID identifier, 337 ID identifier,
218 const tracked_objects::Location& from_here, 338 const tracked_objects::Location& from_here,
219 Task* task, 339 Task* task,
220 int64 delay_ms) { 340 int64 delay_ms) {
221 return PostTaskHelper(identifier, from_here, task, delay_ms, false); 341 return BrowserThreadImpl::PostTaskHelper(
342 identifier, from_here, task, delay_ms, false);
222 } 343 }
223 344
224 // static 345 // static
225 bool BrowserThread::PostTaskAndReply( 346 bool BrowserThread::PostTaskAndReply(
226 ID identifier, 347 ID identifier,
227 const tracked_objects::Location& from_here, 348 const tracked_objects::Location& from_here,
228 const base::Closure& task, 349 const base::Closure& task,
229 const base::Closure& reply) { 350 const base::Closure& reply) {
230 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here, 351 return GetMessageLoopProxyForThread(identifier)->PostTaskAndReply(from_here,
231 task, 352 task,
232 reply); 353 reply);
233 } 354 }
234 355
235 // static 356 // static
236 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { 357 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
237 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 358 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
238 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 359 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
239 // function. 360 // function.
240 // http://crbug.com/63678 361 // http://crbug.com/63678
241 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 362 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
242 MessageLoop* cur_message_loop = MessageLoop::current(); 363 MessageLoop* cur_message_loop = MessageLoop::current();
243 for (int i = 0; i < ID_COUNT; ++i) { 364 for (int i = 0; i < ID_COUNT; ++i) {
244 if (browser_threads_[i] && 365 if (BrowserThreadImpl::browser_threads_[i] &&
245 browser_threads_[i]->message_loop() == cur_message_loop) { 366 BrowserThreadImpl::browser_threads_[i]->message_loop() ==
246 *identifier = browser_threads_[i]->identifier_; 367 cur_message_loop) {
368 *identifier = BrowserThreadImpl::browser_threads_[i]->identifier_;
247 return true; 369 return true;
248 } 370 }
249 } 371 }
250 372
251 return false; 373 return false;
252 } 374 }
253 375
254 // static 376 // static
255 scoped_refptr<base::MessageLoopProxy> 377 scoped_refptr<base::MessageLoopProxy>
256 BrowserThread::GetMessageLoopProxyForThread( 378 BrowserThread::GetMessageLoopProxyForThread(
257 ID identifier) { 379 ID identifier) {
258 scoped_refptr<base::MessageLoopProxy> proxy( 380 scoped_refptr<base::MessageLoopProxy> proxy(
259 new BrowserThreadMessageLoopProxy(identifier)); 381 new BrowserThreadMessageLoopProxy(identifier));
260 return proxy; 382 return proxy;
261 } 383 }
262
263 // static
264 bool BrowserThread::PostTaskHelper(
265 ID identifier,
266 const tracked_objects::Location& from_here,
267 Task* task,
268 int64 delay_ms,
269 bool nestable) {
270 DCHECK(identifier >= 0 && identifier < ID_COUNT);
271 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
272 // order of lifetime. So no need to lock if we know that the other thread
273 // outlives this one.
274 // Note: since the array is so small, ok to loop instead of creating a map,
275 // which would require a lock because std::map isn't thread safe, defeating
276 // the whole purpose of this optimization.
277 ID current_thread;
278 bool guaranteed_to_outlive_target_thread =
279 GetCurrentThreadIdentifier(&current_thread) &&
280 current_thread >= identifier;
281
282 if (!guaranteed_to_outlive_target_thread)
283 lock_.Acquire();
284
285 MessageLoop* message_loop = browser_threads_[identifier] ?
286 browser_threads_[identifier]->message_loop() : NULL;
287 if (message_loop) {
288 if (nestable) {
289 message_loop->PostDelayedTask(from_here, task, delay_ms);
290 } else {
291 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
292 }
293 }
294
295 if (!guaranteed_to_outlive_target_thread)
296 lock_.Release();
297
298 if (!message_loop)
299 delete task;
300
301 return !!message_loop;
302 }
303
304 // static
305 bool BrowserThread::PostTaskHelper(
306 ID identifier,
307 const tracked_objects::Location& from_here,
308 const base::Closure& task,
309 int64 delay_ms,
310 bool nestable) {
311 DCHECK(identifier >= 0 && identifier < ID_COUNT);
312 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
313 // order of lifetime. So no need to lock if we know that the other thread
314 // outlives this one.
315 // Note: since the array is so small, ok to loop instead of creating a map,
316 // which would require a lock because std::map isn't thread safe, defeating
317 // the whole purpose of this optimization.
318 ID current_thread;
319 bool guaranteed_to_outlive_target_thread =
320 GetCurrentThreadIdentifier(&current_thread) &&
321 current_thread >= identifier;
322
323 if (!guaranteed_to_outlive_target_thread)
324 lock_.Acquire();
325
326 MessageLoop* message_loop = browser_threads_[identifier] ?
327 browser_threads_[identifier]->message_loop() : NULL;
328 if (message_loop) {
329 if (nestable) {
330 message_loop->PostDelayedTask(from_here, task, delay_ms);
331 } else {
332 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
333 }
334 }
335
336 if (!guaranteed_to_outlive_target_thread)
337 lock_.Release();
338
339 return !!message_loop;
340 }
OLDNEW
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/browser/browser_thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698