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

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

Issue 9065009: Hook up the SequencedWorkerPool to the browser thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 8 years, 11 months 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/public/browser/browser_thread.h » ('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_impl.h" 5 #include "content/browser/browser_thread_impl.h"
6 6
7 #include "base/atomicops.h" 7 #include "base/atomicops.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/message_loop.h" 10 #include "base/message_loop.h"
11 #include "base/message_loop_proxy.h" 11 #include "base/message_loop_proxy.h"
12 #include "base/threading/sequenced_worker_pool.h"
12 #include "base/threading/thread_restrictions.h" 13 #include "base/threading/thread_restrictions.h"
13 14
14 namespace content { 15 namespace content {
15 16
16 namespace { 17 namespace {
17 18
18 // Friendly names for the well-known threads. 19 // Friendly names for the well-known threads.
19 static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = { 20 static const char* g_browser_thread_names[BrowserThread::ID_COUNT] = {
20 "", // UI (name assembled in browser_main.cc). 21 "", // UI (name assembled in browser_main.cc).
21 "Chrome_DBThread", // DB 22 "Chrome_DBThread", // DB
22 "Chrome_WebKitThread", // WEBKIT_DEPRECATED 23 "Chrome_WebKitThread", // WEBKIT_DEPRECATED
23 "Chrome_FileThread", // FILE 24 "Chrome_FileThread", // FILE
24 "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING 25 "Chrome_FileUserBlockingThread", // FILE_USER_BLOCKING
25 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER 26 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER
26 "Chrome_CacheThread", // CACHE 27 "Chrome_CacheThread", // CACHE
27 "Chrome_IOThread", // IO 28 "Chrome_IOThread", // IO
28 #if defined(OS_CHROMEOS) 29 #if defined(OS_CHROMEOS)
29 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY 30 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY
30 #endif 31 #endif
31 }; 32 };
32 33
33 // This lock protects |g_browser_threads|. Do not read or modify that 34 struct BrowserThreadGlobals {
34 // array without holding this lock. Do not block while holding this 35 BrowserThreadGlobals()
35 // lock. 36 : blocking_pool(new base::SequencedWorkerPool(3, "BrowserBlocking")) {
36 base::LazyInstance<base::Lock, 37 memset(threads, 0,
37 base::LeakyLazyInstanceTraits<base::Lock> > 38 BrowserThread::ID_COUNT * sizeof(BrowserThreadImpl*));
38 g_lock = LAZY_INSTANCE_INITIALIZER; 39 memset(thread_delegates, 0,
40 BrowserThread::ID_COUNT * sizeof(BrowserThreadDelegate*));
41 }
39 42
40 // This array is protected by |g_lock|. The threads are not owned by this 43 // This lock protects |threads|. Do not read or modify that array
41 // array. Typically, the threads are owned on the UI thread by 44 // without holding this lock. Do not block while holding this lock.
42 // content::BrowserMainLoop. BrowserThreadImpl objects remove 45 base::Lock lock;
43 // themselves from this array upon destruction.
44 static BrowserThreadImpl* g_browser_threads[BrowserThread::ID_COUNT];
45 46
46 // Only atomic operations are used on this array. The delegates are 47 // This array is protected by |lock|. The threads are not owned by this
47 // not owned by this array, rather by whoever calls 48 // array. Typically, the threads are owned on the UI thread by
48 // BrowserThread::SetDelegate. 49 // content::BrowserMainLoop. BrowserThreadImpl objects remove themselves from
49 static BrowserThreadDelegate* g_browser_thread_delegates[ 50 // this array upon destruction.
50 BrowserThread::ID_COUNT]; 51 BrowserThreadImpl* threads[BrowserThread::ID_COUNT];
52
53 // Only atomic operations are used on this array. The delegates are not owned
54 // by this array, rather by whoever calls BrowserThread::SetDelegate.
55 BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT];
56
57 // This pointer is deliberately leaked on shutdown. This allows the pool to
58 // implement "continue on shutdown" semantics.
59 base::SequencedWorkerPool* blocking_pool;
60 };
61
62 base::LazyInstance<BrowserThreadGlobals,
63 base::LeakyLazyInstanceTraits<BrowserThreadGlobals> >
64 g_globals = LAZY_INSTANCE_INITIALIZER;
51 65
52 } // namespace 66 } // namespace
53 67
54 BrowserThreadImpl::BrowserThreadImpl(ID identifier) 68 BrowserThreadImpl::BrowserThreadImpl(ID identifier)
55 : Thread(g_browser_thread_names[identifier]), 69 : Thread(g_browser_thread_names[identifier]),
56 identifier_(identifier) { 70 identifier_(identifier) {
57 Initialize(); 71 Initialize();
58 } 72 }
59 73
60 BrowserThreadImpl::BrowserThreadImpl(ID identifier, 74 BrowserThreadImpl::BrowserThreadImpl(ID identifier,
61 MessageLoop* message_loop) 75 MessageLoop* message_loop)
62 : Thread(message_loop->thread_name().c_str()), 76 : Thread(message_loop->thread_name().c_str()),
63 identifier_(identifier) { 77 identifier_(identifier) {
64 set_message_loop(message_loop); 78 set_message_loop(message_loop);
65 Initialize(); 79 Initialize();
66 } 80 }
67 81
82 // static
83 void BrowserThreadImpl::ShutdownThreadPool() {
84 BrowserThreadGlobals& globals = g_globals.Get();
85 globals.blocking_pool->Shutdown();
86 }
87
68 void BrowserThreadImpl::Init() { 88 void BrowserThreadImpl::Init() {
89 BrowserThreadGlobals& globals = g_globals.Get();
90
69 using base::subtle::AtomicWord; 91 using base::subtle::AtomicWord;
70 AtomicWord* storage = 92 AtomicWord* storage =
71 reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]); 93 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
72 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); 94 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
73 BrowserThreadDelegate* delegate = 95 BrowserThreadDelegate* delegate =
74 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); 96 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
75 if (delegate) 97 if (delegate)
76 delegate->Init(); 98 delegate->Init();
77 } 99 }
78 100
79 void BrowserThreadImpl::CleanUp() { 101 void BrowserThreadImpl::CleanUp() {
102 BrowserThreadGlobals& globals = g_globals.Get();
103
80 using base::subtle::AtomicWord; 104 using base::subtle::AtomicWord;
81 AtomicWord* storage = 105 AtomicWord* storage =
82 reinterpret_cast<AtomicWord*>(&g_browser_thread_delegates[identifier_]); 106 reinterpret_cast<AtomicWord*>(&globals.thread_delegates[identifier_]);
83 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage); 107 AtomicWord stored_pointer = base::subtle::NoBarrier_Load(storage);
84 BrowserThreadDelegate* delegate = 108 BrowserThreadDelegate* delegate =
85 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); 109 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
86 110
87 if (delegate) 111 if (delegate)
88 delegate->CleanUp(); 112 delegate->CleanUp();
89 } 113 }
90 114
91 void BrowserThreadImpl::Initialize() { 115 void BrowserThreadImpl::Initialize() {
92 base::AutoLock lock(g_lock.Get()); 116 BrowserThreadGlobals& globals = g_globals.Get();
117
118 base::AutoLock lock(globals.lock);
93 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); 119 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
94 DCHECK(g_browser_threads[identifier_] == NULL); 120 DCHECK(globals.threads[identifier_] == NULL);
95 g_browser_threads[identifier_] = this; 121 globals.threads[identifier_] = this;
96 } 122 }
97 123
98 BrowserThreadImpl::~BrowserThreadImpl() { 124 BrowserThreadImpl::~BrowserThreadImpl() {
99 // All Thread subclasses must call Stop() in the destructor. This is 125 // All Thread subclasses must call Stop() in the destructor. This is
100 // doubly important here as various bits of code check they are on 126 // doubly important here as various bits of code check they are on
101 // the right BrowserThread. 127 // the right BrowserThread.
102 Stop(); 128 Stop();
103 129
104 base::AutoLock lock(g_lock.Get()); 130 BrowserThreadGlobals& globals = g_globals.Get();
105 g_browser_threads[identifier_] = NULL; 131 base::AutoLock lock(globals.lock);
132 globals.threads[identifier_] = NULL;
106 #ifndef NDEBUG 133 #ifndef NDEBUG
107 // Double check that the threads are ordered correctly in the enumeration. 134 // Double check that the threads are ordered correctly in the enumeration.
108 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { 135 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
109 DCHECK(!g_browser_threads[i]) << 136 DCHECK(!globals.threads[i]) <<
110 "Threads must be listed in the reverse order that they die"; 137 "Threads must be listed in the reverse order that they die";
111 } 138 }
112 #endif 139 #endif
113 } 140 }
114 141
115 // static 142 // static
116 bool BrowserThreadImpl::PostTaskHelper( 143 bool BrowserThreadImpl::PostTaskHelper(
117 BrowserThread::ID identifier, 144 BrowserThread::ID identifier,
118 const tracked_objects::Location& from_here, 145 const tracked_objects::Location& from_here,
119 Task* task, 146 Task* task,
120 int64 delay_ms, 147 int64 delay_ms,
121 bool nestable) { 148 bool nestable) {
122 DCHECK(identifier >= 0 && identifier < ID_COUNT); 149 DCHECK(identifier >= 0 && identifier < ID_COUNT);
123 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in 150 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
124 // order of lifetime. So no need to lock if we know that the other thread 151 // order of lifetime. So no need to lock if we know that the other thread
125 // outlives this one. 152 // outlives this one.
126 // Note: since the array is so small, ok to loop instead of creating a map, 153 // Note: since the array is so small, ok to loop instead of creating a map,
127 // which would require a lock because std::map isn't thread safe, defeating 154 // which would require a lock because std::map isn't thread safe, defeating
128 // the whole purpose of this optimization. 155 // the whole purpose of this optimization.
129 BrowserThread::ID current_thread; 156 BrowserThread::ID current_thread;
130 bool guaranteed_to_outlive_target_thread = 157 bool guaranteed_to_outlive_target_thread =
131 GetCurrentThreadIdentifier(&current_thread) && 158 GetCurrentThreadIdentifier(&current_thread) &&
132 current_thread <= identifier; 159 current_thread <= identifier;
133 160
161 BrowserThreadGlobals& globals = g_globals.Get();
134 if (!guaranteed_to_outlive_target_thread) 162 if (!guaranteed_to_outlive_target_thread)
135 g_lock.Get().Acquire(); 163 globals.lock.Acquire();
136 164
137 MessageLoop* message_loop = g_browser_threads[identifier] ? 165 MessageLoop* message_loop = globals.threads[identifier] ?
138 g_browser_threads[identifier]->message_loop() : NULL; 166 globals.threads[identifier]->message_loop() : NULL;
139 if (message_loop) { 167 if (message_loop) {
140 if (nestable) { 168 if (nestable) {
141 message_loop->PostDelayedTask(from_here, task, delay_ms); 169 message_loop->PostDelayedTask(from_here, task, delay_ms);
142 } else { 170 } else {
143 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms); 171 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
144 } 172 }
145 } 173 }
146 174
147 if (!guaranteed_to_outlive_target_thread) 175 if (!guaranteed_to_outlive_target_thread)
148 g_lock.Get().Release(); 176 globals.lock.Release();
149 177
150 if (!message_loop) 178 if (!message_loop)
151 delete task; 179 delete task;
152 180
153 return !!message_loop; 181 return !!message_loop;
154 } 182 }
155 183
156 // static 184 // static
157 bool BrowserThreadImpl::PostTaskHelper( 185 bool BrowserThreadImpl::PostTaskHelper(
158 BrowserThread::ID identifier, 186 BrowserThread::ID identifier,
159 const tracked_objects::Location& from_here, 187 const tracked_objects::Location& from_here,
160 const base::Closure& task, 188 const base::Closure& task,
161 int64 delay_ms, 189 int64 delay_ms,
162 bool nestable) { 190 bool nestable) {
163 DCHECK(identifier >= 0 && identifier < ID_COUNT); 191 DCHECK(identifier >= 0 && identifier < ID_COUNT);
164 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in 192 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
165 // order of lifetime. So no need to lock if we know that the other thread 193 // order of lifetime. So no need to lock if we know that the other thread
166 // outlives this one. 194 // outlives this one.
167 // Note: since the array is so small, ok to loop instead of creating a map, 195 // Note: since the array is so small, ok to loop instead of creating a map,
168 // which would require a lock because std::map isn't thread safe, defeating 196 // which would require a lock because std::map isn't thread safe, defeating
169 // the whole purpose of this optimization. 197 // the whole purpose of this optimization.
170 BrowserThread::ID current_thread; 198 BrowserThread::ID current_thread;
171 bool guaranteed_to_outlive_target_thread = 199 bool guaranteed_to_outlive_target_thread =
172 GetCurrentThreadIdentifier(&current_thread) && 200 GetCurrentThreadIdentifier(&current_thread) &&
173 current_thread <= identifier; 201 current_thread <= identifier;
174 202
203 BrowserThreadGlobals& globals = g_globals.Get();
175 if (!guaranteed_to_outlive_target_thread) 204 if (!guaranteed_to_outlive_target_thread)
176 g_lock.Get().Acquire(); 205 globals.lock.Acquire();
177 206
178 MessageLoop* message_loop = g_browser_threads[identifier] ? 207 MessageLoop* message_loop = globals.threads[identifier] ?
179 g_browser_threads[identifier]->message_loop() : NULL; 208 globals.threads[identifier]->message_loop() : NULL;
180 if (message_loop) { 209 if (message_loop) {
181 if (nestable) { 210 if (nestable) {
182 message_loop->PostDelayedTask(from_here, task, delay_ms); 211 message_loop->PostDelayedTask(from_here, task, delay_ms);
183 } else { 212 } else {
184 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms); 213 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
185 } 214 }
186 } 215 }
187 216
188 if (!guaranteed_to_outlive_target_thread) 217 if (!guaranteed_to_outlive_target_thread)
189 g_lock.Get().Release(); 218 globals.lock.Release();
190 219
191 return !!message_loop; 220 return !!message_loop;
192 } 221 }
193 222
194 // An implementation of MessageLoopProxy to be used in conjunction 223 // An implementation of MessageLoopProxy to be used in conjunction
195 // with BrowserThread. 224 // with BrowserThread.
196 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy { 225 class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
197 public: 226 public:
198 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier) 227 explicit BrowserThreadMessageLoopProxy(BrowserThread::ID identifier)
199 : id_(identifier) { 228 : id_(identifier) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 virtual bool BelongsToCurrentThread() { 278 virtual bool BelongsToCurrentThread() {
250 return BrowserThread::CurrentlyOn(id_); 279 return BrowserThread::CurrentlyOn(id_);
251 } 280 }
252 281
253 private: 282 private:
254 BrowserThread::ID id_; 283 BrowserThread::ID id_;
255 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy); 284 DISALLOW_COPY_AND_ASSIGN(BrowserThreadMessageLoopProxy);
256 }; 285 };
257 286
258 // static 287 // static
259 bool BrowserThread::IsWellKnownThread(ID identifier) { 288 bool BrowserThread::PostBlockingPoolTask(
260 base::AutoLock lock(g_lock.Get()); 289 const tracked_objects::Location& from_here,
261 return (identifier >= 0 && identifier < ID_COUNT && 290 const base::Closure& task) {
262 g_browser_threads[identifier]); 291 return g_globals.Get().blocking_pool->PostWorkerTask(from_here, task);
263 } 292 }
264 293
265 // static 294 // static
295 bool BrowserThread::PostBlockingPoolSequencedTask(
296 const std::string& sequence_token_name,
297 const tracked_objects::Location& from_here,
298 const base::Closure& task) {
299 return g_globals.Get().blocking_pool->PostNamedSequencedWorkerTask(
300 sequence_token_name, from_here, task);
301 }
302
303 // static
304 base::SequencedWorkerPool* BrowserThread::GetBlockingPool() {
305 return g_globals.Get().blocking_pool;
306 }
307
308 // static
309 bool BrowserThread::IsWellKnownThread(ID identifier) {
310 BrowserThreadGlobals& globals = g_globals.Get();
311 base::AutoLock lock(globals.lock);
312 return (identifier >= 0 && identifier < ID_COUNT &&
313 globals.threads[identifier]);
314 }
315
316 // static
266 bool BrowserThread::CurrentlyOn(ID identifier) { 317 bool BrowserThread::CurrentlyOn(ID identifier) {
267 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 318 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
268 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 319 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
269 // function. 320 // function.
270 // http://crbug.com/63678 321 // http://crbug.com/63678
271 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 322 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
272 base::AutoLock lock(g_lock.Get()); 323 BrowserThreadGlobals& globals = g_globals.Get();
324 base::AutoLock lock(globals.lock);
273 DCHECK(identifier >= 0 && identifier < ID_COUNT); 325 DCHECK(identifier >= 0 && identifier < ID_COUNT);
274 return g_browser_threads[identifier] && 326 return globals.threads[identifier] &&
275 g_browser_threads[identifier]->message_loop() == 327 globals.threads[identifier]->message_loop() ==
276 MessageLoop::current(); 328 MessageLoop::current();
277 } 329 }
278 330
279 // static 331 // static
280 bool BrowserThread::IsMessageLoopValid(ID identifier) { 332 bool BrowserThread::IsMessageLoopValid(ID identifier) {
281 base::AutoLock lock(g_lock.Get()); 333 BrowserThreadGlobals& globals = g_globals.Get();
334 base::AutoLock lock(globals.lock);
282 DCHECK(identifier >= 0 && identifier < ID_COUNT); 335 DCHECK(identifier >= 0 && identifier < ID_COUNT);
283 return g_browser_threads[identifier] && 336 return globals.threads[identifier] &&
284 g_browser_threads[identifier]->message_loop(); 337 globals.threads[identifier]->message_loop();
285 } 338 }
286 339
287 // static 340 // static
288 bool BrowserThread::PostTask(ID identifier, 341 bool BrowserThread::PostTask(ID identifier,
289 const tracked_objects::Location& from_here, 342 const tracked_objects::Location& from_here,
290 const base::Closure& task) { 343 const base::Closure& task) {
291 return BrowserThreadImpl::PostTaskHelper( 344 return BrowserThreadImpl::PostTaskHelper(
292 identifier, from_here, task, 0, true); 345 identifier, from_here, task, 0, true);
293 } 346 }
294 347
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 421 }
369 422
370 // static 423 // static
371 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { 424 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
372 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 425 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
373 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 426 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
374 // function. 427 // function.
375 // http://crbug.com/63678 428 // http://crbug.com/63678
376 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 429 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
377 MessageLoop* cur_message_loop = MessageLoop::current(); 430 MessageLoop* cur_message_loop = MessageLoop::current();
431 BrowserThreadGlobals& globals = g_globals.Get();
378 for (int i = 0; i < ID_COUNT; ++i) { 432 for (int i = 0; i < ID_COUNT; ++i) {
379 if (g_browser_threads[i] && 433 if (globals.threads[i] &&
380 g_browser_threads[i]->message_loop() == cur_message_loop) { 434 globals.threads[i]->message_loop() == cur_message_loop) {
381 *identifier = g_browser_threads[i]->identifier_; 435 *identifier = globals.threads[i]->identifier_;
382 return true; 436 return true;
383 } 437 }
384 } 438 }
385 439
386 return false; 440 return false;
387 } 441 }
388 442
389 // static 443 // static
390 scoped_refptr<base::MessageLoopProxy> 444 scoped_refptr<base::MessageLoopProxy>
391 BrowserThread::GetMessageLoopProxyForThread( 445 BrowserThread::GetMessageLoopProxyForThread(ID identifier) {
392 ID identifier) {
393 scoped_refptr<base::MessageLoopProxy> proxy( 446 scoped_refptr<base::MessageLoopProxy> proxy(
394 new BrowserThreadMessageLoopProxy(identifier)); 447 new BrowserThreadMessageLoopProxy(identifier));
395 return proxy; 448 return proxy;
396 } 449 }
397 450
398 // static 451 // static
399 MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { 452 MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
400 base::AutoLock lock(g_lock.Get()); 453 BrowserThreadGlobals& globals = g_globals.Get();
401 base::Thread* thread = g_browser_threads[identifier]; 454 base::AutoLock lock(globals.lock);
455 base::Thread* thread = globals.threads[identifier];
402 DCHECK(thread); 456 DCHECK(thread);
403 MessageLoop* loop = thread->message_loop(); 457 MessageLoop* loop = thread->message_loop();
404 return loop; 458 return loop;
405 } 459 }
406 460
407 // static 461 // static
408 void BrowserThread::SetDelegate(ID identifier, 462 void BrowserThread::SetDelegate(ID identifier,
409 BrowserThreadDelegate* delegate) { 463 BrowserThreadDelegate* delegate) {
410 using base::subtle::AtomicWord; 464 using base::subtle::AtomicWord;
465 BrowserThreadGlobals& globals = g_globals.Get();
411 AtomicWord* storage = reinterpret_cast<AtomicWord*>( 466 AtomicWord* storage = reinterpret_cast<AtomicWord*>(
412 &g_browser_thread_delegates[identifier]); 467 &globals.thread_delegates[identifier]);
413 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( 468 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
414 storage, reinterpret_cast<AtomicWord>(delegate)); 469 storage, reinterpret_cast<AtomicWord>(delegate));
415 470
416 // This catches registration when previously registered. 471 // This catches registration when previously registered.
417 DCHECK(!delegate || !old_pointer); 472 DCHECK(!delegate || !old_pointer);
418 } 473 }
419 474
420 } // namespace content 475 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/public/browser/browser_thread.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698