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 "content/browser/browser_thread_impl.h" | 5 #include "content/browser/browser_thread_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/atomicops.h" | 9 #include "base/atomicops.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = { | 24 static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = { |
25 "", // UI (name assembled in browser_main.cc). | 25 "", // UI (name assembled in browser_main.cc). |
26 "Chrome_DBThread", // DB | 26 "Chrome_DBThread", // DB |
27 "Chrome_FileThread", // FILE | 27 "Chrome_FileThread", // FILE |
28 "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING | 28 "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING |
29 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER | 29 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER |
30 "Chrome_CacheThread", // CACHE | 30 "Chrome_CacheThread", // CACHE |
31 "Chrome_IOThread", // IO | 31 "Chrome_IOThread", // IO |
32 }; | 32 }; |
33 | 33 |
| 34 // An implementation of MessageLoopProxy to be used in conjunction |
| 35 // with BrowserThread. |
| 36 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { |
| 37 public: |
| 38 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) |
| 39 : id_(identifier) { |
| 40 } |
| 41 |
| 42 // MessageLoopProxy implementation. |
| 43 virtual bool PostDelayedTask( |
| 44 const tracked_objects::Location& from_here, |
| 45 const base::Closure& task, base::TimeDelta delay) OVERRIDE { |
| 46 return BrowserThread::PostDelayedTask(id_, from_here, task, delay); |
| 47 } |
| 48 |
| 49 virtual bool PostNonNestableDelayedTask( |
| 50 const tracked_objects::Location& from_here, |
| 51 const base::Closure& task, |
| 52 base::TimeDelta delay) OVERRIDE { |
| 53 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, |
| 54 delay); |
| 55 } |
| 56 |
| 57 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { |
| 58 return BrowserThread::CurrentlyOn(id_); |
| 59 } |
| 60 |
| 61 protected: |
| 62 virtual ~BrowserThreadMessageLoopProxy() {} |
| 63 |
| 64 private: |
| 65 BrowserThread::ID id_; |
| 66 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); |
| 67 }; |
| 68 |
| 69 // A separate helper is used just for the proxies, in order to avoid needing |
| 70 // to initialize the globals to create a proxy. |
| 71 struct BrowserThreadProxies { |
| 72 BrowserThreadProxies() { |
| 73 for (int i = 0; i < BrowserThread::ID_COUNT; ++i) { |
| 74 proxies[i] = |
| 75 new BrowserThreadMessageLoopProxy(static_cast<BrowserThread::ID>(i)); |
| 76 } |
| 77 } |
| 78 |
| 79 scoped_refptr<base::MessageLoopProxy> proxies[BrowserThread::ID_COUNT]; |
| 80 }; |
| 81 |
| 82 base::LazyInstance<BrowserThreadProxies>::Leaky |
| 83 g_proxies = LAZY_INSTANCE_INITIALIZER; |
| 84 |
34 struct BrowserThreadGlobals { | 85 struct BrowserThreadGlobals { |
35 BrowserThreadGlobals() | 86 BrowserThreadGlobals() |
36 : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) { | 87 : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) { |
37 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0])); | 88 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0])); |
38 memset(thread_delegates, 0, | 89 memset(thread_delegates, 0, |
39 BrowserThread::ID_COUNT * sizeof(thread_delegates[0])); | 90 BrowserThread::ID_COUNT * sizeof(thread_delegates[0])); |
40 } | 91 } |
41 | 92 |
42 // This lock protects |threads|. Do not read or modify that array | 93 // This lock protects |threads|. Do not read or modify that array |
43 // without holding this lock. Do not block while holding this lock. | 94 // without holding this lock. Do not block while holding this lock. |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 message_loop->PostNonNestableDelayedTask(from_here, task, delay); | 318 message_loop->PostNonNestableDelayedTask(from_here, task, delay); |
268 } | 319 } |
269 } | 320 } |
270 | 321 |
271 if (!target_thread_outlives_current) | 322 if (!target_thread_outlives_current) |
272 globals.lock.Release(); | 323 globals.lock.Release(); |
273 | 324 |
274 return !!message_loop; | 325 return !!message_loop; |
275 } | 326 } |
276 | 327 |
277 // An implementation of MessageLoopProxy to be used in conjunction | |
278 // with BrowserThread. | |
279 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { | |
280 public: | |
281 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) | |
282 : id_(identifier) { | |
283 } | |
284 | |
285 // MessageLoopProxy implementation. | |
286 virtual bool PostDelayedTask( | |
287 const tracked_objects::Location& from_here, | |
288 const base::Closure& task, base::TimeDelta delay) OVERRIDE { | |
289 return BrowserThread::PostDelayedTask(id_, from_here, task, delay); | |
290 } | |
291 | |
292 virtual bool PostNonNestableDelayedTask( | |
293 const tracked_objects::Location& from_here, | |
294 const base::Closure& task, | |
295 base::TimeDelta delay) OVERRIDE { | |
296 return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task, | |
297 delay); | |
298 } | |
299 | |
300 virtual bool RunsTasksOnCurrentThread() const OVERRIDE { | |
301 return BrowserThread::CurrentlyOn(id_); | |
302 } | |
303 | |
304 protected: | |
305 virtual ~BrowserThreadMessageLoopProxy() {} | |
306 | |
307 private: | |
308 BrowserThread::ID id_; | |
309 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); | |
310 }; | |
311 | |
312 // static | 328 // static |
313 bool BrowserThread::PostBlockingPoolTask( | 329 bool BrowserThread::PostBlockingPoolTask( |
314 const tracked_objects::Location& from_here, | 330 const tracked_objects::Location& from_here, |
315 const base::Closure& task) { | 331 const base::Closure& task) { |
316 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task); | 332 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task); |
317 } | 333 } |
318 | 334 |
319 // static | 335 // static |
320 bool BrowserThread::PostBlockingPoolTaskAndReply( | 336 bool BrowserThread::PostBlockingPoolTaskAndReply( |
321 const tracked_objects::Location& from_here, | 337 const tracked_objects::Location& from_here, |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
470 return true; | 486 return true; |
471 } | 487 } |
472 } | 488 } |
473 | 489 |
474 return false; | 490 return false; |
475 } | 491 } |
476 | 492 |
477 // static | 493 // static |
478 scoped_refptr<base::MessageLoopProxy> | 494 scoped_refptr<base::MessageLoopProxy> |
479 BrowserThread::GetMessageLoopProxyForThread(ID identifier) { | 495 BrowserThread::GetMessageLoopProxyForThread(ID identifier) { |
480 return make_scoped_refptr(new BrowserThreadMessageLoopProxy(identifier)); | 496 return g_proxies.Get().proxies[identifier]; |
481 } | 497 } |
482 | 498 |
483 // static | 499 // static |
484 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { | 500 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { |
485 if (g_globals == NULL) | 501 if (g_globals == NULL) |
486 return NULL; | 502 return NULL; |
487 | 503 |
488 BrowserThreadGlobals& globals = g_globals.Get(); | 504 BrowserThreadGlobals& globals = g_globals.Get(); |
489 base::AutoLock lock(globals.lock); | 505 base::AutoLock lock(globals.lock); |
490 base::Thread* thread = globals.threads[identifier]; | 506 base::Thread* thread = globals.threads[identifier]; |
(...skipping 10 matching lines...) Expand all Loading... |
501 AtomicWord* storage = reinterpret_cast<AtomicWord*>( | 517 AtomicWord* storage = reinterpret_cast<AtomicWord*>( |
502 &globals.thread_delegates[identifier]); | 518 &globals.thread_delegates[identifier]); |
503 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 519 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
504 storage, reinterpret_cast<AtomicWord>(delegate)); | 520 storage, reinterpret_cast<AtomicWord>(delegate)); |
505 | 521 |
506 // This catches registration when previously registered. | 522 // This catches registration when previously registered. |
507 DCHECK(!delegate || !old_pointer); | 523 DCHECK(!delegate || !old_pointer); |
508 } | 524 } |
509 | 525 |
510 } // namespace content | 526 } // namespace content |
OLD | NEW |