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 |