| 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.h> | 7 #include <string.h> |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 | 10 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 new BrowserThreadTaskRunner(static_cast<BrowserThread::ID>(i)); | 92 new BrowserThreadTaskRunner(static_cast<BrowserThread::ID>(i)); |
| 93 } | 93 } |
| 94 } | 94 } |
| 95 | 95 |
| 96 scoped_refptr<base::SingleThreadTaskRunner> proxies[BrowserThread::ID_COUNT]; | 96 scoped_refptr<base::SingleThreadTaskRunner> proxies[BrowserThread::ID_COUNT]; |
| 97 }; | 97 }; |
| 98 | 98 |
| 99 base::LazyInstance<BrowserThreadTaskRunners>::Leaky g_task_runners = | 99 base::LazyInstance<BrowserThreadTaskRunners>::Leaky g_task_runners = |
| 100 LAZY_INSTANCE_INITIALIZER; | 100 LAZY_INSTANCE_INITIALIZER; |
| 101 | 101 |
| 102 using BrowserThreadDelegateAtomicPtr = base::subtle::AtomicWord; |
| 103 |
| 102 struct BrowserThreadGlobals { | 104 struct BrowserThreadGlobals { |
| 103 BrowserThreadGlobals() | 105 BrowserThreadGlobals() |
| 104 : blocking_pool( | 106 : blocking_pool( |
| 105 new base::SequencedWorkerPool(3, | 107 new base::SequencedWorkerPool(3, |
| 106 "BrowserBlocking", | 108 "BrowserBlocking", |
| 107 base::TaskPriority::USER_VISIBLE)) { | 109 base::TaskPriority::USER_VISIBLE)) { |
| 108 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0])); | 110 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0])); |
| 109 memset(thread_ids, 0, BrowserThread::ID_COUNT * sizeof(thread_ids[0])); | 111 memset(thread_ids, 0, BrowserThread::ID_COUNT * sizeof(thread_ids[0])); |
| 110 memset(thread_delegates, 0, | |
| 111 BrowserThread::ID_COUNT * sizeof(thread_delegates[0])); | |
| 112 } | 112 } |
| 113 | 113 |
| 114 // This lock protects |threads| and |thread_ids|. Do not read or modify those | 114 // This lock protects |threads| and |thread_ids|. Do not read or modify those |
| 115 // arrays without holding this lock. Do not block while holding this lock. | 115 // arrays without holding this lock. Do not block while holding this lock. |
| 116 base::Lock lock; | 116 base::Lock lock; |
| 117 | 117 |
| 118 // This array is protected by |lock|. IDs in this array are populated as soon | 118 // This array is protected by |lock|. IDs in this array are populated as soon |
| 119 // as their respective thread is started and are never reset. | 119 // as their respective thread is started and are never reset. |
| 120 base::PlatformThreadId thread_ids[BrowserThread::ID_COUNT]; | 120 base::PlatformThreadId thread_ids[BrowserThread::ID_COUNT]; |
| 121 | 121 |
| 122 // This array is protected by |lock|. The threads are not owned by this | 122 // This array is protected by |lock|. The threads are not owned by this |
| 123 // array. Typically, the threads are owned on the UI thread by | 123 // array. Typically, the threads are owned on the UI thread by |
| 124 // BrowserMainLoop. BrowserThreadImpl objects remove themselves from this | 124 // BrowserMainLoop. BrowserThreadImpl objects remove themselves from this |
| 125 // array upon destruction. | 125 // array upon destruction. |
| 126 BrowserThreadImpl* threads[BrowserThread::ID_COUNT]; | 126 BrowserThreadImpl* threads[BrowserThread::ID_COUNT]; |
| 127 | 127 |
| 128 // Only atomic operations are used on this array. The delegates are not owned | 128 // Only atomic operations are used on this pointer. The delegate isn't owned |
| 129 // by this array, rather by whoever calls BrowserThread::SetDelegate. | 129 // by BrowserThreadGlobals, rather by whoever calls |
| 130 BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT]; | 130 // BrowserThread::SetIOThreadDelegate. |
| 131 BrowserThreadDelegateAtomicPtr io_thread_delegate = 0; |
| 131 | 132 |
| 132 const scoped_refptr<base::SequencedWorkerPool> blocking_pool; | 133 const scoped_refptr<base::SequencedWorkerPool> blocking_pool; |
| 133 }; | 134 }; |
| 134 | 135 |
| 135 base::LazyInstance<BrowserThreadGlobals>::Leaky | 136 base::LazyInstance<BrowserThreadGlobals>::Leaky |
| 136 g_globals = LAZY_INSTANCE_INITIALIZER; | 137 g_globals = LAZY_INSTANCE_INITIALIZER; |
| 137 | 138 |
| 138 } // namespace | 139 } // namespace |
| 139 | 140 |
| 140 BrowserThreadImpl::BrowserThreadImpl(ID identifier) | 141 BrowserThreadImpl::BrowserThreadImpl(ID identifier) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 // We don't want to create a pool if none exists. | 179 // We don't want to create a pool if none exists. |
| 179 if (g_globals == nullptr) | 180 if (g_globals == nullptr) |
| 180 return; | 181 return; |
| 181 g_globals.Get().blocking_pool->FlushForTesting(); | 182 g_globals.Get().blocking_pool->FlushForTesting(); |
| 182 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); | 183 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); |
| 183 } | 184 } |
| 184 | 185 |
| 185 void BrowserThreadImpl::Init() { | 186 void BrowserThreadImpl::Init() { |
| 186 BrowserThreadGlobals& globals = g_globals.Get(); | 187 BrowserThreadGlobals& globals = g_globals.Get(); |
| 187 | 188 |
| 188 if (BrowserThread::CurrentlyOn(BrowserThread::DB) || | 189 if (identifier_ == BrowserThread::DB || |
| 189 BrowserThread::CurrentlyOn(BrowserThread::FILE) || | 190 identifier_ == BrowserThread::FILE || |
| 190 BrowserThread::CurrentlyOn(BrowserThread::FILE_USER_BLOCKING) || | 191 identifier_ == BrowserThread::FILE_USER_BLOCKING || |
| 191 BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER) || | 192 identifier_ == BrowserThread::PROCESS_LAUNCHER || |
| 192 BrowserThread::CurrentlyOn(BrowserThread::CACHE)) { | 193 identifier_ == BrowserThread::CACHE) { |
| 193 base::MessageLoop* message_loop = base::MessageLoop::current(); | 194 base::MessageLoop* message_loop = base::MessageLoop::current(); |
| 194 message_loop->DisallowNesting(); | 195 message_loop->DisallowNesting(); |
| 195 message_loop->DisallowTaskObservers(); | 196 message_loop->DisallowTaskObservers(); |
| 196 } | 197 } |
| 197 | 198 |
| 198 using base::subtle::AtomicWord; | 199 if (identifier_ == BrowserThread::IO) { |
| 199 AtomicWord* storage = | 200 BrowserThreadDelegateAtomicPtr delegate = |
| 200 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]); | 201 base::subtle::NoBarrier_Load(&globals.io_thread_delegate); |
| 201 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); | 202 if (delegate) |
| 202 BrowserThreadDelegate* delegate = | 203 reinterpret_cast<BrowserThreadDelegate*>(delegate)->Init(); |
| 203 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); | 204 } |
| 204 if (delegate) | |
| 205 delegate->Init(); | |
| 206 } | 205 } |
| 207 | 206 |
| 208 // We disable optimizations for this block of functions so the compiler doesn't | 207 // We disable optimizations for this block of functions so the compiler doesn't |
| 209 // merge them all together. | 208 // merge them all together. |
| 210 MSVC_DISABLE_OPTIMIZE() | 209 MSVC_DISABLE_OPTIMIZE() |
| 211 MSVC_PUSH_DISABLE_WARNING(4748) | 210 MSVC_PUSH_DISABLE_WARNING(4748) |
| 212 | 211 |
| 213 NOINLINE void BrowserThreadImpl::UIThreadRun(base::RunLoop* run_loop) { | 212 NOINLINE void BrowserThreadImpl::UIThreadRun(base::RunLoop* run_loop) { |
| 214 volatile int line_number = __LINE__; | 213 volatile int line_number = __LINE__; |
| 215 Thread::Run(run_loop); | 214 Thread::Run(run_loop); |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 } | 291 } |
| 293 | 292 |
| 294 // |identifier_| must be set to a valid enum value in the constructor, so it | 293 // |identifier_| must be set to a valid enum value in the constructor, so it |
| 295 // should be impossible to reach here. | 294 // should be impossible to reach here. |
| 296 CHECK(false); | 295 CHECK(false); |
| 297 } | 296 } |
| 298 | 297 |
| 299 void BrowserThreadImpl::CleanUp() { | 298 void BrowserThreadImpl::CleanUp() { |
| 300 BrowserThreadGlobals& globals = g_globals.Get(); | 299 BrowserThreadGlobals& globals = g_globals.Get(); |
| 301 | 300 |
| 302 using base::subtle::AtomicWord; | 301 if (identifier_ == BrowserThread::IO) { |
| 303 AtomicWord* storage = | 302 BrowserThreadDelegateAtomicPtr delegate = |
| 304 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]); | 303 base::subtle::NoBarrier_Load(&globals.io_thread_delegate); |
| 305 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); | 304 if (delegate) |
| 306 BrowserThreadDelegate* delegate = | 305 reinterpret_cast<BrowserThreadDelegate*>(delegate)->CleanUp(); |
| 307 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); | 306 } |
| 308 | |
| 309 if (delegate) | |
| 310 delegate->CleanUp(); | |
| 311 | 307 |
| 312 // PostTaskHelper() accesses the message loop while holding this lock. | 308 // PostTaskHelper() accesses the message loop while holding this lock. |
| 313 // However, the message loop will soon be destructed without any locking. So | 309 // However, the message loop will soon be destructed without any locking. So |
| 314 // to prevent a race with accessing the message loop in PostTaskHelper(), | 310 // to prevent a race with accessing the message loop in PostTaskHelper(), |
| 315 // remove this thread from the global array now. | 311 // remove this thread from the global array now. |
| 316 base::AutoLock lock(globals.lock); | 312 base::AutoLock lock(globals.lock); |
| 317 globals.threads[identifier_] = nullptr; | 313 globals.threads[identifier_] = nullptr; |
| 318 } | 314 } |
| 319 | 315 |
| 320 void BrowserThreadImpl::Initialize() { | 316 void BrowserThreadImpl::Initialize() { |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 | 560 |
| 565 return false; | 561 return false; |
| 566 } | 562 } |
| 567 | 563 |
| 568 // static | 564 // static |
| 569 scoped_refptr<base::SingleThreadTaskRunner> | 565 scoped_refptr<base::SingleThreadTaskRunner> |
| 570 BrowserThread::GetTaskRunnerForThread(ID identifier) { | 566 BrowserThread::GetTaskRunnerForThread(ID identifier) { |
| 571 return g_task_runners.Get().proxies[identifier]; | 567 return g_task_runners.Get().proxies[identifier]; |
| 572 } | 568 } |
| 573 | 569 |
| 574 void BrowserThread::SetDelegate(ID identifier, | 570 // static |
| 575 BrowserThreadDelegate* delegate) { | 571 void BrowserThread::SetIOThreadDelegate(BrowserThreadDelegate* delegate) { |
| 576 using base::subtle::AtomicWord; | |
| 577 BrowserThreadGlobals& globals = g_globals.Get(); | 572 BrowserThreadGlobals& globals = g_globals.Get(); |
| 578 AtomicWord* storage = reinterpret_cast<AtomicWord*>( | 573 BrowserThreadDelegateAtomicPtr old_delegate = |
| 579 &globals.thread_delegates[identifier]); | 574 base::subtle::NoBarrier_AtomicExchange( |
| 580 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( | 575 &globals.io_thread_delegate, |
| 581 storage, reinterpret_cast<AtomicWord>(delegate)); | 576 reinterpret_cast<BrowserThreadDelegateAtomicPtr>(delegate)); |
| 582 | 577 |
| 583 // This catches registration when previously registered. | 578 // This catches registration when previously registered. |
| 584 DCHECK(!delegate || !old_pointer); | 579 DCHECK(!delegate || !old_delegate); |
| 585 } | 580 } |
| 586 | 581 |
| 587 } // namespace content | 582 } // namespace content |
| OLD | NEW |