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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 | 62 |
63 } // namespace | 63 } // namespace |
64 | 64 |
65 BrowserThreadImpl::BrowserThreadImpl(ID identifier) | 65 BrowserThreadImpl::BrowserThreadImpl(ID identifier) |
66 : Thread(g_browser_thread_names[identifier]), | 66 : Thread(g_browser_thread_names[identifier]), |
67 identifier_(identifier) { | 67 identifier_(identifier) { |
68 Initialize(); | 68 Initialize(); |
69 } | 69 } |
70 | 70 |
71 BrowserThreadImpl::BrowserThreadImpl(ID identifier, | 71 BrowserThreadImpl::BrowserThreadImpl(ID identifier, |
72 MessageLoop* message_loop) | 72 base::MessageLoop* message_loop) |
73 : Thread(message_loop->thread_name().c_str()), | 73 : Thread(message_loop->thread_name().c_str()), identifier_(identifier) { |
74 identifier_(identifier) { | |
75 set_message_loop(message_loop); | 74 set_message_loop(message_loop); |
76 Initialize(); | 75 Initialize(); |
77 } | 76 } |
78 | 77 |
79 // static | 78 // static |
80 void BrowserThreadImpl::ShutdownThreadPool() { | 79 void BrowserThreadImpl::ShutdownThreadPool() { |
81 // The goal is to make it impossible for chrome to 'infinite loop' during | 80 // The goal is to make it impossible for chrome to 'infinite loop' during |
82 // shutdown, but to reasonably expect that all BLOCKING_SHUTDOWN tasks queued | 81 // shutdown, but to reasonably expect that all BLOCKING_SHUTDOWN tasks queued |
83 // during shutdown get run. There's nothing particularly scientific about the | 82 // during shutdown get run. There's nothing particularly scientific about the |
84 // number chosen. | 83 // number chosen. |
(...skipping 21 matching lines...) Expand all Loading... |
106 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); | 105 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); |
107 if (delegate) | 106 if (delegate) |
108 delegate->Init(); | 107 delegate->Init(); |
109 } | 108 } |
110 | 109 |
111 // We disable optimizations for this block of functions so the compiler doesn't | 110 // We disable optimizations for this block of functions so the compiler doesn't |
112 // merge them all together. | 111 // merge them all together. |
113 MSVC_DISABLE_OPTIMIZE() | 112 MSVC_DISABLE_OPTIMIZE() |
114 MSVC_PUSH_DISABLE_WARNING(4748) | 113 MSVC_PUSH_DISABLE_WARNING(4748) |
115 | 114 |
116 NOINLINE void BrowserThreadImpl::UIThreadRun(MessageLoop* message_loop) { | 115 NOINLINE void BrowserThreadImpl::UIThreadRun(base::MessageLoop* message_loop) { |
117 volatile int line_number = __LINE__; | 116 volatile int line_number = __LINE__; |
118 Thread::Run(message_loop); | 117 Thread::Run(message_loop); |
119 CHECK_GT(line_number, 0); | 118 CHECK_GT(line_number, 0); |
120 } | 119 } |
121 | 120 |
122 NOINLINE void BrowserThreadImpl::DBThreadRun(MessageLoop* message_loop) { | 121 NOINLINE void BrowserThreadImpl::DBThreadRun(base::MessageLoop* message_loop) { |
123 volatile int line_number = __LINE__; | 122 volatile int line_number = __LINE__; |
124 Thread::Run(message_loop); | 123 Thread::Run(message_loop); |
125 CHECK_GT(line_number, 0); | 124 CHECK_GT(line_number, 0); |
126 } | 125 } |
127 | 126 |
128 NOINLINE void BrowserThreadImpl::WebKitThreadRun(MessageLoop* message_loop) { | 127 NOINLINE void BrowserThreadImpl::WebKitThreadRun( |
| 128 base::MessageLoop* message_loop) { |
129 volatile int line_number = __LINE__; | 129 volatile int line_number = __LINE__; |
130 Thread::Run(message_loop); | 130 Thread::Run(message_loop); |
131 CHECK_GT(line_number, 0); | 131 CHECK_GT(line_number, 0); |
132 } | 132 } |
133 | 133 |
134 NOINLINE void BrowserThreadImpl::FileThreadRun(MessageLoop* message_loop) { | 134 NOINLINE void BrowserThreadImpl::FileThreadRun( |
| 135 base::MessageLoop* message_loop) { |
135 volatile int line_number = __LINE__; | 136 volatile int line_number = __LINE__; |
136 Thread::Run(message_loop); | 137 Thread::Run(message_loop); |
137 CHECK_GT(line_number, 0); | 138 CHECK_GT(line_number, 0); |
138 } | 139 } |
139 | 140 |
140 NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun( | 141 NOINLINE void BrowserThreadImpl::FileUserBlockingThreadRun( |
141 MessageLoop* message_loop) { | 142 base::MessageLoop* message_loop) { |
142 volatile int line_number = __LINE__; | 143 volatile int line_number = __LINE__; |
143 Thread::Run(message_loop); | 144 Thread::Run(message_loop); |
144 CHECK_GT(line_number, 0); | 145 CHECK_GT(line_number, 0); |
145 } | 146 } |
146 | 147 |
147 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun( | 148 NOINLINE void BrowserThreadImpl::ProcessLauncherThreadRun( |
148 MessageLoop* message_loop) { | 149 base::MessageLoop* message_loop) { |
149 volatile int line_number = __LINE__; | 150 volatile int line_number = __LINE__; |
150 Thread::Run(message_loop); | 151 Thread::Run(message_loop); |
151 CHECK_GT(line_number, 0); | 152 CHECK_GT(line_number, 0); |
152 } | 153 } |
153 | 154 |
154 NOINLINE void BrowserThreadImpl::CacheThreadRun(MessageLoop* message_loop) { | 155 NOINLINE void BrowserThreadImpl::CacheThreadRun( |
| 156 base::MessageLoop* message_loop) { |
155 volatile int line_number = __LINE__; | 157 volatile int line_number = __LINE__; |
156 Thread::Run(message_loop); | 158 Thread::Run(message_loop); |
157 CHECK_GT(line_number, 0); | 159 CHECK_GT(line_number, 0); |
158 } | 160 } |
159 | 161 |
160 NOINLINE void BrowserThreadImpl::IOThreadRun(MessageLoop* message_loop) { | 162 NOINLINE void BrowserThreadImpl::IOThreadRun(base::MessageLoop* message_loop) { |
161 volatile int line_number = __LINE__; | 163 volatile int line_number = __LINE__; |
162 Thread::Run(message_loop); | 164 Thread::Run(message_loop); |
163 CHECK_GT(line_number, 0); | 165 CHECK_GT(line_number, 0); |
164 } | 166 } |
165 | 167 |
166 MSVC_POP_WARNING() | 168 MSVC_POP_WARNING() |
167 MSVC_ENABLE_OPTIMIZE(); | 169 MSVC_ENABLE_OPTIMIZE(); |
168 | 170 |
169 void BrowserThreadImpl::Run(MessageLoop* message_loop) { | 171 void BrowserThreadImpl::Run(base::MessageLoop* message_loop) { |
170 BrowserThread::ID thread_id; | 172 BrowserThread::ID thread_id; |
171 if (!GetCurrentThreadIdentifier(&thread_id)) | 173 if (!GetCurrentThreadIdentifier(&thread_id)) |
172 return Thread::Run(message_loop); | 174 return Thread::Run(message_loop); |
173 | 175 |
174 switch (thread_id) { | 176 switch (thread_id) { |
175 case BrowserThread::UI: | 177 case BrowserThread::UI: |
176 return UIThreadRun(message_loop); | 178 return UIThreadRun(message_loop); |
177 case BrowserThread::DB: | 179 case BrowserThread::DB: |
178 return DBThreadRun(message_loop); | 180 return DBThreadRun(message_loop); |
179 case BrowserThread::WEBKIT_DEPRECATED: | 181 case BrowserThread::WEBKIT_DEPRECATED: |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 // the whole purpose of this optimization. | 254 // the whole purpose of this optimization. |
253 BrowserThread::ID current_thread; | 255 BrowserThread::ID current_thread; |
254 bool target_thread_outlives_current = | 256 bool target_thread_outlives_current = |
255 GetCurrentThreadIdentifier(¤t_thread) && | 257 GetCurrentThreadIdentifier(¤t_thread) && |
256 current_thread >= identifier; | 258 current_thread >= identifier; |
257 | 259 |
258 BrowserThreadGlobals& globals = g_globals.Get(); | 260 BrowserThreadGlobals& globals = g_globals.Get(); |
259 if (!target_thread_outlives_current) | 261 if (!target_thread_outlives_current) |
260 globals.lock.Acquire(); | 262 globals.lock.Acquire(); |
261 | 263 |
262 MessageLoop* message_loop = globals.threads[identifier] ? | 264 base::MessageLoop* message_loop = |
263 globals.threads[identifier]->message_loop() : NULL; | 265 globals.threads[identifier] ? globals.threads[identifier]->message_loop() |
| 266 : NULL; |
264 if (message_loop) { | 267 if (message_loop) { |
265 if (nestable) { | 268 if (nestable) { |
266 message_loop->PostDelayedTask(from_here, task, delay); | 269 message_loop->PostDelayedTask(from_here, task, delay); |
267 } else { | 270 } else { |
268 message_loop->PostNonNestableDelayedTask(from_here, task, delay); | 271 message_loop->PostNonNestableDelayedTask(from_here, task, delay); |
269 } | 272 } |
270 } | 273 } |
271 | 274 |
272 if (!target_thread_outlives_current) | 275 if (!target_thread_outlives_current) |
273 globals.lock.Release(); | 276 globals.lock.Release(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
354 bool BrowserThread::CurrentlyOn(ID identifier) { | 357 bool BrowserThread::CurrentlyOn(ID identifier) { |
355 // We shouldn't use MessageLoop::current() since it uses LazyInstance which | 358 // We shouldn't use MessageLoop::current() since it uses LazyInstance which |
356 // may be deleted by ~AtExitManager when a WorkerPool thread calls this | 359 // may be deleted by ~AtExitManager when a WorkerPool thread calls this |
357 // function. | 360 // function. |
358 // http://crbug.com/63678 | 361 // http://crbug.com/63678 |
359 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; | 362 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; |
360 BrowserThreadGlobals& globals = g_globals.Get(); | 363 BrowserThreadGlobals& globals = g_globals.Get(); |
361 base::AutoLock lock(globals.lock); | 364 base::AutoLock lock(globals.lock); |
362 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 365 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
363 return globals.threads[identifier] && | 366 return globals.threads[identifier] && |
364 globals.threads[identifier]->message_loop() == MessageLoop::current(); | 367 globals.threads[identifier]->message_loop() == |
| 368 base::MessageLoop::current(); |
365 } | 369 } |
366 | 370 |
367 // static | 371 // static |
368 bool BrowserThread::IsMessageLoopValid(ID identifier) { | 372 bool BrowserThread::IsMessageLoopValid(ID identifier) { |
369 if (g_globals == NULL) | 373 if (g_globals == NULL) |
370 return false; | 374 return false; |
371 | 375 |
372 BrowserThreadGlobals& globals = g_globals.Get(); | 376 BrowserThreadGlobals& globals = g_globals.Get(); |
373 base::AutoLock lock(globals.lock); | 377 base::AutoLock lock(globals.lock); |
374 DCHECK(identifier >= 0 && identifier < ID_COUNT); | 378 DCHECK(identifier >= 0 && identifier < ID_COUNT); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 // static | 430 // static |
427 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { | 431 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { |
428 if (g_globals == NULL) | 432 if (g_globals == NULL) |
429 return false; | 433 return false; |
430 | 434 |
431 // We shouldn't use MessageLoop::current() since it uses LazyInstance which | 435 // We shouldn't use MessageLoop::current() since it uses LazyInstance which |
432 // may be deleted by ~AtExitManager when a WorkerPool thread calls this | 436 // may be deleted by ~AtExitManager when a WorkerPool thread calls this |
433 // function. | 437 // function. |
434 // http://crbug.com/63678 | 438 // http://crbug.com/63678 |
435 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; | 439 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; |
436 MessageLoop* cur_message_loop = MessageLoop::current(); | 440 base::MessageLoop* cur_message_loop = base::MessageLoop::current(); |
437 BrowserThreadGlobals& globals = g_globals.Get(); | 441 BrowserThreadGlobals& globals = g_globals.Get(); |
438 for (int i = 0; i < ID_COUNT; ++i) { | 442 for (int i = 0; i < ID_COUNT; ++i) { |
439 if (globals.threads[i] && | 443 if (globals.threads[i] && |
440 globals.threads[i]->message_loop() == cur_message_loop) { | 444 globals.threads[i]->message_loop() == cur_message_loop) { |
441 *identifier = globals.threads[i]->identifier_; | 445 *identifier = globals.threads[i]->identifier_; |
442 return true; | 446 return true; |
443 } | 447 } |
444 } | 448 } |
445 | 449 |
446 return false; | 450 return false; |
447 } | 451 } |
448 | 452 |
449 // static | 453 // static |
450 scoped_refptr<base::MessageLoopProxy> | 454 scoped_refptr<base::MessageLoopProxy> |
451 BrowserThread::GetMessageLoopProxyForThread(ID identifier) { | 455 BrowserThread::GetMessageLoopProxyForThread(ID identifier) { |
452 return make_scoped_refptr(new BrowserThreadMessageLoopProxy(identifier)); | 456 return make_scoped_refptr(new BrowserThreadMessageLoopProxy(identifier)); |
453 } | 457 } |
454 | 458 |
455 // static | 459 // static |
456 MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { | 460 MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { |
457 if (g_globals == NULL) | 461 if (g_globals == NULL) |
458 return NULL; | 462 return NULL; |
459 | 463 |
460 BrowserThreadGlobals& globals = g_globals.Get(); | 464 BrowserThreadGlobals& globals = g_globals.Get(); |
461 base::AutoLock lock(globals.lock); | 465 base::AutoLock lock(globals.lock); |
462 base::Thread* thread = globals.threads[identifier]; | 466 base::Thread* thread = globals.threads[identifier]; |
463 DCHECK(thread); | 467 DCHECK(thread); |
464 MessageLoop* loop = thread->message_loop(); | 468 base::MessageLoop* loop = thread->message_loop(); |
465 return loop; | 469 return loop; |
466 } | 470 } |
467 | 471 |
468 // static | 472 // static |
469 void BrowserThread::SetDelegate(ID identifier, | 473 void BrowserThread::SetDelegate(ID identifier, |
470 BrowserThreadDelegate* delegate) { | 474 BrowserThreadDelegate* delegate) { |
471 using base::subtle::AtomicWord; | 475 using base::subtle::AtomicWord; |
472 BrowserThreadGlobals& globals = g_globals.Get(); | 476 BrowserThreadGlobals& globals = g_globals.Get(); |
473 AtomicWord* storage = reinterpret_cast<AtomicWord*>( | 477 AtomicWord* storage = reinterpret_cast<AtomicWord*>( |
474 &globals.thread_delegates[identifier]); | 478 &globals.thread_delegates[identifier]); |
475 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 479 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( |
476 storage, reinterpret_cast<AtomicWord>(delegate)); | 480 storage, reinterpret_cast<AtomicWord>(delegate)); |
477 | 481 |
478 // This catches registration when previously registered. | 482 // This catches registration when previously registered. |
479 DCHECK(!delegate || !old_pointer); | 483 DCHECK(!delegate || !old_pointer); |
480 } | 484 } |
481 | 485 |
482 } // namespace content | 486 } // namespace content |
OLD | NEW |