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

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

Issue 8493016: content: Remove 16 exit time destructors and 15 static initializers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 9 years, 1 month 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
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/bind.h" 7 #include "base/bind.h"
8 #include "base/lazy_instance.h"
8 #include "base/message_loop.h" 9 #include "base/message_loop.h"
9 #include "base/message_loop_proxy.h" 10 #include "base/message_loop_proxy.h"
10 #include "base/threading/thread_restrictions.h" 11 #include "base/threading/thread_restrictions.h"
11 12
12 namespace { 13 namespace {
13 14
14 // Friendly names for the well-known threads. 15 // Friendly names for the well-known threads.
15 static const char* browser_thread_names[content::BrowserThread::ID_COUNT] = { 16 static const char* browser_thread_names[content::BrowserThread::ID_COUNT] = {
16 "", // UI (name assembled in browser_main.cc). 17 "", // UI (name assembled in browser_main.cc).
17 "Chrome_DBThread", // DB 18 "Chrome_DBThread", // DB
18 "Chrome_WebKitThread", // WEBKIT 19 "Chrome_WebKitThread", // WEBKIT
19 "Chrome_FileThread", // FILE 20 "Chrome_FileThread", // FILE
20 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER 21 "Chrome_ProcessLauncherThread", // PROCESS_LAUNCHER
21 "Chrome_CacheThread", // CACHE 22 "Chrome_CacheThread", // CACHE
22 "Chrome_IOThread", // IO 23 "Chrome_IOThread", // IO
23 #if defined(OS_CHROMEOS) 24 #if defined(OS_CHROMEOS)
24 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY 25 "Chrome_WebSocketproxyThread", // WEB_SOCKET_PROXY
25 #endif 26 #endif
26 }; 27 };
27 28
28 } // namespace 29 } // namespace
29 30
30 namespace content { 31 namespace content {
31 32
32 base::Lock BrowserThreadImpl::lock_; 33 namespace {
33 34
34 BrowserThread* BrowserThreadImpl::browser_threads_[ID_COUNT]; 35 // This lock protects |g_browser_threads|. Do not read or modify that array
36 // without holding this lock. Do not block while holding this lock.
37 base::LazyInstance<base::Lock,
38 base::LeakyLazyInstanceTraits<base::Lock> >
39 g_lock(base::LINKER_INITIALIZED);
40
41
42 // An array of the BrowserThread objects. This array is protected by |g_lock|.
43 // The threads are not owned by this array. Typically, the threads are owned
44 // on the UI thread by the g_browser_process object. BrowserThreads remove
45 // themselves from this array upon destruction.
46 BrowserThread* g_browser_threads[BrowserThread::ID_COUNT];
47
48 } // namespace
35 49
36 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier) 50 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier)
37 : BrowserThread(identifier) { 51 : BrowserThread(identifier) {
38 } 52 }
39 53
40 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier, 54 BrowserThreadImpl::BrowserThreadImpl(BrowserThread::ID identifier,
41 MessageLoop* message_loop) 55 MessageLoop* message_loop)
42 : BrowserThread(identifier, message_loop) { 56 : BrowserThread(identifier, message_loop) {
43 } 57 }
44 58
(...skipping 14 matching lines...) Expand all
59 // outlives this one. 73 // outlives this one.
60 // Note: since the array is so small, ok to loop instead of creating a map, 74 // Note: since the array is so small, ok to loop instead of creating a map,
61 // which would require a lock because std::map isn't thread safe, defeating 75 // which would require a lock because std::map isn't thread safe, defeating
62 // the whole purpose of this optimization. 76 // the whole purpose of this optimization.
63 BrowserThread::ID current_thread; 77 BrowserThread::ID current_thread;
64 bool guaranteed_to_outlive_target_thread = 78 bool guaranteed_to_outlive_target_thread =
65 GetCurrentThreadIdentifier(&current_thread) && 79 GetCurrentThreadIdentifier(&current_thread) &&
66 current_thread >= identifier; 80 current_thread >= identifier;
67 81
68 if (!guaranteed_to_outlive_target_thread) 82 if (!guaranteed_to_outlive_target_thread)
69 BrowserThreadImpl::lock_.Acquire(); 83 g_lock.Get().Acquire();
70 84
71 MessageLoop* message_loop = BrowserThreadImpl::browser_threads_[identifier] ? 85 MessageLoop* message_loop = g_browser_threads[identifier] ?
72 BrowserThreadImpl::browser_threads_[identifier]->message_loop() : NULL; 86 g_browser_threads[identifier]->message_loop() : NULL;
73 if (message_loop) { 87 if (message_loop) {
74 if (nestable) { 88 if (nestable) {
75 message_loop->PostDelayedTask(from_here, task, delay_ms); 89 message_loop->PostDelayedTask(from_here, task, delay_ms);
76 } else { 90 } else {
77 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms); 91 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
78 } 92 }
79 } 93 }
80 94
81 if (!guaranteed_to_outlive_target_thread) 95 if (!guaranteed_to_outlive_target_thread)
82 BrowserThreadImpl::lock_.Release(); 96 g_lock.Get().Release();
83 97
84 if (!message_loop) 98 if (!message_loop)
85 delete task; 99 delete task;
86 100
87 return !!message_loop; 101 return !!message_loop;
88 } 102 }
89 103
90 // static 104 // static
91 bool BrowserThreadImpl::PostTaskHelper( 105 bool BrowserThreadImpl::PostTaskHelper(
92 BrowserThread::ID identifier, 106 BrowserThread::ID identifier,
93 const tracked_objects::Location& from_here, 107 const tracked_objects::Location& from_here,
94 const base::Closure& task, 108 const base::Closure& task,
95 int64 delay_ms, 109 int64 delay_ms,
96 bool nestable) { 110 bool nestable) {
97 DCHECK(identifier >= 0 && identifier < ID_COUNT); 111 DCHECK(identifier >= 0 && identifier < ID_COUNT);
98 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in 112 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
99 // order of lifetime. So no need to lock if we know that the other thread 113 // order of lifetime. So no need to lock if we know that the other thread
100 // outlives this one. 114 // outlives this one.
101 // Note: since the array is so small, ok to loop instead of creating a map, 115 // Note: since the array is so small, ok to loop instead of creating a map,
102 // which would require a lock because std::map isn't thread safe, defeating 116 // which would require a lock because std::map isn't thread safe, defeating
103 // the whole purpose of this optimization. 117 // the whole purpose of this optimization.
104 BrowserThread::ID current_thread; 118 BrowserThread::ID current_thread;
105 bool guaranteed_to_outlive_target_thread = 119 bool guaranteed_to_outlive_target_thread =
106 GetCurrentThreadIdentifier(&current_thread) && 120 GetCurrentThreadIdentifier(&current_thread) &&
107 current_thread >= identifier; 121 current_thread >= identifier;
108 122
109 if (!guaranteed_to_outlive_target_thread) 123 if (!guaranteed_to_outlive_target_thread)
110 lock_.Acquire(); 124 g_lock.Get().Acquire();
111 125
112 MessageLoop* message_loop = browser_threads_[identifier] ? 126 MessageLoop* message_loop = g_browser_threads[identifier] ?
113 browser_threads_[identifier]->message_loop() : NULL; 127 g_browser_threads[identifier]->message_loop() : NULL;
114 if (message_loop) { 128 if (message_loop) {
115 if (nestable) { 129 if (nestable) {
116 message_loop->PostDelayedTask(from_here, task, delay_ms); 130 message_loop->PostDelayedTask(from_here, task, delay_ms);
117 } else { 131 } else {
118 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms); 132 message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
119 } 133 }
120 } 134 }
121 135
122 if (!guaranteed_to_outlive_target_thread) 136 if (!guaranteed_to_outlive_target_thread)
123 lock_.Release(); 137 g_lock.Get().Release();
124 138
125 return !!message_loop; 139 return !!message_loop;
126 } 140 }
127 141
128 // TODO(joi): Remove 142 // TODO(joi): Remove
129 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier) 143 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier)
130 : BrowserThread(identifier) { 144 : BrowserThread(identifier) {
131 } 145 }
132 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier, 146 DeprecatedBrowserThread::DeprecatedBrowserThread(BrowserThread::ID identifier,
133 MessageLoop* message_loop) 147 MessageLoop* message_loop)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 223
210 BrowserThread::BrowserThread(ID identifier, 224 BrowserThread::BrowserThread(ID identifier,
211 MessageLoop* message_loop) 225 MessageLoop* message_loop)
212 : Thread(message_loop->thread_name().c_str()), 226 : Thread(message_loop->thread_name().c_str()),
213 identifier_(identifier) { 227 identifier_(identifier) {
214 set_message_loop(message_loop); 228 set_message_loop(message_loop);
215 Initialize(); 229 Initialize();
216 } 230 }
217 231
218 void BrowserThread::Initialize() { 232 void BrowserThread::Initialize() {
219 base::AutoLock lock(BrowserThreadImpl::lock_); 233 base::AutoLock lock(g_lock.Get());
220 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); 234 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
221 DCHECK(BrowserThreadImpl::browser_threads_[identifier_] == NULL); 235 DCHECK(g_browser_threads[identifier_] == NULL);
222 BrowserThreadImpl::browser_threads_[identifier_] = this; 236 g_browser_threads[identifier_] = this;
223 } 237 }
224 238
225 BrowserThread::~BrowserThread() { 239 BrowserThread::~BrowserThread() {
226 // Stop the thread here, instead of the parent's class destructor. This is so 240 // Stop the thread here, instead of the parent's class destructor. This is so
227 // that if there are pending tasks that run, code that checks that it's on the 241 // that if there are pending tasks that run, code that checks that it's on the
228 // correct BrowserThread succeeds. 242 // correct BrowserThread succeeds.
229 Stop(); 243 Stop();
230 244
231 base::AutoLock lock(BrowserThreadImpl::lock_); 245 base::AutoLock lock(g_lock.Get());
232 BrowserThreadImpl::browser_threads_[identifier_] = NULL; 246 g_browser_threads[identifier_] = NULL;
233 #ifndef NDEBUG 247 #ifndef NDEBUG
234 // Double check that the threads are ordered correctly in the enumeration. 248 // Double check that the threads are ordered correctly in the enumeration.
235 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { 249 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
236 DCHECK(!BrowserThreadImpl::browser_threads_[i]) << 250 DCHECK(!g_browser_threads[i]) <<
237 "Threads must be listed in the reverse order that they die"; 251 "Threads must be listed in the reverse order that they die";
238 } 252 }
239 #endif 253 #endif
240 } 254 }
241 255
242 // static 256 // static
243 bool BrowserThread::IsWellKnownThread(ID identifier) { 257 bool BrowserThread::IsWellKnownThread(ID identifier) {
244 base::AutoLock lock(BrowserThreadImpl::lock_); 258 base::AutoLock lock(g_lock.Get());
245 return (identifier >= 0 && identifier < ID_COUNT && 259 return (identifier >= 0 && identifier < ID_COUNT &&
246 BrowserThreadImpl::browser_threads_[identifier]); 260 g_browser_threads[identifier]);
247 } 261 }
248 262
249 // static 263 // static
250 bool BrowserThread::CurrentlyOn(ID identifier) { 264 bool BrowserThread::CurrentlyOn(ID identifier) {
251 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 265 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
252 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 266 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
253 // function. 267 // function.
254 // http://crbug.com/63678 268 // http://crbug.com/63678
255 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 269 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
256 base::AutoLock lock(BrowserThreadImpl::lock_); 270 base::AutoLock lock(g_lock.Get());
257 DCHECK(identifier >= 0 && identifier < ID_COUNT); 271 DCHECK(identifier >= 0 && identifier < ID_COUNT);
258 return BrowserThreadImpl::browser_threads_[identifier] && 272 return g_browser_threads[identifier] &&
259 BrowserThreadImpl::browser_threads_[identifier]->message_loop() == 273 g_browser_threads[identifier]->message_loop() ==
260 MessageLoop::current(); 274 MessageLoop::current();
261 } 275 }
262 276
263 // static 277 // static
264 bool BrowserThread::IsMessageLoopValid(ID identifier) { 278 bool BrowserThread::IsMessageLoopValid(ID identifier) {
265 base::AutoLock lock(BrowserThreadImpl::lock_); 279 base::AutoLock lock(g_lock.Get());
266 DCHECK(identifier >= 0 && identifier < ID_COUNT); 280 DCHECK(identifier >= 0 && identifier < ID_COUNT);
267 return BrowserThreadImpl::browser_threads_[identifier] && 281 return g_browser_threads[identifier] &&
268 BrowserThreadImpl::browser_threads_[identifier]->message_loop(); 282 g_browser_threads[identifier]->message_loop();
269 } 283 }
270 284
271 // static 285 // static
272 bool BrowserThread::PostTask(ID identifier, 286 bool BrowserThread::PostTask(ID identifier,
273 const tracked_objects::Location& from_here, 287 const tracked_objects::Location& from_here,
274 const base::Closure& task) { 288 const base::Closure& task) {
275 return BrowserThreadImpl::PostTaskHelper( 289 return BrowserThreadImpl::PostTaskHelper(
276 identifier, from_here, task, 0, true); 290 identifier, from_here, task, 0, true);
277 } 291 }
278 292
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 367
354 // static 368 // static
355 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { 369 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
356 // We shouldn't use MessageLoop::current() since it uses LazyInstance which 370 // We shouldn't use MessageLoop::current() since it uses LazyInstance which
357 // may be deleted by ~AtExitManager when a WorkerPool thread calls this 371 // may be deleted by ~AtExitManager when a WorkerPool thread calls this
358 // function. 372 // function.
359 // http://crbug.com/63678 373 // http://crbug.com/63678
360 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton; 374 base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
361 MessageLoop* cur_message_loop = MessageLoop::current(); 375 MessageLoop* cur_message_loop = MessageLoop::current();
362 for (int i = 0; i < ID_COUNT; ++i) { 376 for (int i = 0; i < ID_COUNT; ++i) {
363 if (BrowserThreadImpl::browser_threads_[i] && 377 if (g_browser_threads[i] &&
364 BrowserThreadImpl::browser_threads_[i]->message_loop() == 378 g_browser_threads[i]->message_loop() == cur_message_loop) {
365 cur_message_loop) { 379 *identifier = g_browser_threads[i]->identifier_;
366 *identifier = BrowserThreadImpl::browser_threads_[i]->identifier_;
367 return true; 380 return true;
368 } 381 }
369 } 382 }
370 383
371 return false; 384 return false;
372 } 385 }
373 386
374 // static 387 // static
375 scoped_refptr<base::MessageLoopProxy> 388 scoped_refptr<base::MessageLoopProxy>
376 BrowserThread::GetMessageLoopProxyForThread( 389 BrowserThread::GetMessageLoopProxyForThread(
377 ID identifier) { 390 ID identifier) {
378 scoped_refptr<base::MessageLoopProxy> proxy( 391 scoped_refptr<base::MessageLoopProxy> proxy(
379 new BrowserThreadMessageLoopProxy(identifier)); 392 new BrowserThreadMessageLoopProxy(identifier));
380 return proxy; 393 return proxy;
381 } 394 }
382 395
383 } // namespace content 396 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698