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

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

Issue 2186213002: Revert of Ensure BrowserThread::CurrentlyOn is correct through MessageLoop teardown (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 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
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/browser/browser_thread_unittest.cc » ('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) 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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 struct BrowserThreadGlobals { 102 struct BrowserThreadGlobals {
103 BrowserThreadGlobals() 103 BrowserThreadGlobals()
104 : blocking_pool( 104 : blocking_pool(
105 new base::SequencedWorkerPool(3, 105 new base::SequencedWorkerPool(3,
106 "BrowserBlocking", 106 "BrowserBlocking",
107 base::TaskPriority::USER_VISIBLE)) { 107 base::TaskPriority::USER_VISIBLE)) {
108 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0])); 108 memset(threads, 0, BrowserThread::ID_COUNT * sizeof(threads[0]));
109 memset(thread_ids, 0, BrowserThread::ID_COUNT * sizeof(thread_ids[0]));
110 memset(thread_delegates, 0, 109 memset(thread_delegates, 0,
111 BrowserThread::ID_COUNT * sizeof(thread_delegates[0])); 110 BrowserThread::ID_COUNT * sizeof(thread_delegates[0]));
112 } 111 }
113 112
114 // This lock protects |threads| and |thread_ids|. Do not read or modify those 113 // This lock protects |threads|. Do not read or modify that array
115 // arrays without holding this lock. Do not block while holding this lock. 114 // without holding this lock. Do not block while holding this lock.
116 base::Lock lock; 115 base::Lock lock;
117 116
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.
120 base::PlatformThreadId thread_ids[BrowserThread::ID_COUNT];
121
122 // This array is protected by |lock|. The threads are not owned by this 117 // 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 118 // array. Typically, the threads are owned on the UI thread by
124 // BrowserMainLoop. BrowserThreadImpl objects remove themselves from this 119 // BrowserMainLoop. BrowserThreadImpl objects remove themselves from this
125 // array upon destruction. 120 // array upon destruction.
126 BrowserThreadImpl* threads[BrowserThread::ID_COUNT]; 121 BrowserThreadImpl* threads[BrowserThread::ID_COUNT];
127 122
128 // Only atomic operations are used on this array. The delegates are not owned 123 // Only atomic operations are used on this array. The delegates are not owned
129 // by this array, rather by whoever calls BrowserThread::SetDelegate. 124 // by this array, rather by whoever calls BrowserThread::SetDelegate.
130 BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT]; 125 BrowserThreadDelegate* thread_delegates[BrowserThread::ID_COUNT];
131 126
132 const scoped_refptr<base::SequencedWorkerPool> blocking_pool; 127 const scoped_refptr<base::SequencedWorkerPool> blocking_pool;
133 }; 128 };
134 129
135 base::LazyInstance<BrowserThreadGlobals>::Leaky 130 base::LazyInstance<BrowserThreadGlobals>::Leaky
136 g_globals = LAZY_INSTANCE_INITIALIZER; 131 g_globals = LAZY_INSTANCE_INITIALIZER;
137 132
138 } // namespace 133 } // namespace
139 134
140 BrowserThreadImpl::BrowserThreadImpl(ID identifier) 135 BrowserThreadImpl::BrowserThreadImpl(ID identifier)
141 : Thread(GetThreadName(identifier)), identifier_(identifier) { 136 : Thread(GetThreadName(identifier)), identifier_(identifier) {
142 Initialize(); 137 Initialize();
143
144 // Unit tests may create multiple TestBrowserThreadBundles, causing the same
145 // BrowserThread ID to be reinitialized. We explicitly clear the thread ID
146 // here so Start() can sanity check.
147 BrowserThreadGlobals& globals = g_globals.Get();
148 base::AutoLock lock(globals.lock);
149 globals.thread_ids[identifier] = base::kInvalidThreadId;
150 } 138 }
151 139
152 BrowserThreadImpl::BrowserThreadImpl(ID identifier, 140 BrowserThreadImpl::BrowserThreadImpl(ID identifier,
153 base::MessageLoop* message_loop) 141 base::MessageLoop* message_loop)
154 : Thread(GetThreadName(identifier)), identifier_(identifier) { 142 : Thread(GetThreadName(identifier)), identifier_(identifier) {
155 set_message_loop(message_loop); 143 set_message_loop(message_loop);
156 Initialize(); 144 Initialize();
157
158 // If constructed with an explicit message loop, this is a fake BrowserThread
159 // which runs on the current thread.
160 BrowserThreadGlobals& globals = g_globals.Get();
161 base::AutoLock lock(globals.lock);
162 globals.thread_ids[identifier] = base::PlatformThread::CurrentId();
163 } 145 }
164 146
165 // static 147 // static
166 void BrowserThreadImpl::ShutdownThreadPool() { 148 void BrowserThreadImpl::ShutdownThreadPool() {
167 // The goal is to make it impossible for chrome to 'infinite loop' during 149 // The goal is to make it impossible for chrome to 'infinite loop' during
168 // shutdown, but to reasonably expect that all BLOCKING_SHUTDOWN tasks queued 150 // shutdown, but to reasonably expect that all BLOCKING_SHUTDOWN tasks queued
169 // during shutdown get run. There's nothing particularly scientific about the 151 // during shutdown get run. There's nothing particularly scientific about the
170 // number chosen. 152 // number chosen.
171 const int kMaxNewShutdownBlockingTasks = 1000; 153 const int kMaxNewShutdownBlockingTasks = 1000;
172 BrowserThreadGlobals& globals = g_globals.Get(); 154 BrowserThreadGlobals& globals = g_globals.Get();
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 globals.threads[identifier_] = nullptr; 310 globals.threads[identifier_] = nullptr;
329 #ifndef NDEBUG 311 #ifndef NDEBUG
330 // Double check that the threads are ordered correctly in the enumeration. 312 // Double check that the threads are ordered correctly in the enumeration.
331 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { 313 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
332 DCHECK(!globals.threads[i]) << 314 DCHECK(!globals.threads[i]) <<
333 "Threads must be listed in the reverse order that they die"; 315 "Threads must be listed in the reverse order that they die";
334 } 316 }
335 #endif 317 #endif
336 } 318 }
337 319
338 bool BrowserThreadImpl::Start() {
339 return StartWithOptions(base::Thread::Options());
340 }
341
342 bool BrowserThreadImpl::StartWithOptions(const Options& options) { 320 bool BrowserThreadImpl::StartWithOptions(const Options& options) {
343 // The global thread table needs to be locked while a new thread is 321 // The global thread table needs to be locked while a new thread is
344 // starting, as the new thread can asynchronously start touching the 322 // starting, as the new thread can asynchronously start touching the
345 // table (and other thread's message_loop). 323 // table (and other thread's message_loop).
346 BrowserThreadGlobals& globals = g_globals.Get(); 324 BrowserThreadGlobals& globals = g_globals.Get();
347 base::AutoLock lock(globals.lock); 325 base::AutoLock lock(globals.lock);
348 DCHECK_EQ(globals.thread_ids[identifier_], base::kInvalidThreadId); 326 return Thread::StartWithOptions(options);
349 bool result = Thread::StartWithOptions(options);
350 globals.thread_ids[identifier_] = GetThreadId();
351 return result;
352 } 327 }
353 328
354 bool BrowserThreadImpl::StartAndWaitForTesting() {
355 if (!Start())
356 return false;
357 WaitUntilThreadStarted();
358 return true;
359 }
360 // static 329 // static
361 bool BrowserThreadImpl::PostTaskHelper( 330 bool BrowserThreadImpl::PostTaskHelper(
362 BrowserThread::ID identifier, 331 BrowserThread::ID identifier,
363 const tracked_objects::Location& from_here, 332 const tracked_objects::Location& from_here,
364 const base::Closure& task, 333 const base::Closure& task,
365 base::TimeDelta delay, 334 base::TimeDelta delay,
366 bool nestable) { 335 bool nestable) {
367 DCHECK_GE(identifier, 0); 336 DCHECK_GE(identifier, 0);
368 DCHECK_LT(identifier, ID_COUNT); 337 DCHECK_LT(identifier, ID_COUNT);
369 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in 338 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 DCHECK_LT(identifier, ID_COUNT); 418 DCHECK_LT(identifier, ID_COUNT);
450 return globals.threads[identifier] != nullptr; 419 return globals.threads[identifier] != nullptr;
451 } 420 }
452 421
453 // static 422 // static
454 bool BrowserThread::CurrentlyOn(ID identifier) { 423 bool BrowserThread::CurrentlyOn(ID identifier) {
455 BrowserThreadGlobals& globals = g_globals.Get(); 424 BrowserThreadGlobals& globals = g_globals.Get();
456 base::AutoLock lock(globals.lock); 425 base::AutoLock lock(globals.lock);
457 DCHECK_GE(identifier, 0); 426 DCHECK_GE(identifier, 0);
458 DCHECK_LT(identifier, ID_COUNT); 427 DCHECK_LT(identifier, ID_COUNT);
459 return base::PlatformThread::CurrentId() == globals.thread_ids[identifier]; 428 return globals.threads[identifier] &&
429 globals.threads[identifier]->message_loop() ==
430 base::MessageLoop::current();
460 } 431 }
461 432
462 // static 433 // static
463 std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) { 434 std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
464 std::string actual_name = base::PlatformThread::GetName(); 435 std::string actual_name = base::PlatformThread::GetName();
465 if (actual_name.empty()) 436 if (actual_name.empty())
466 actual_name = "Unknown Thread"; 437 actual_name = "Unknown Thread";
467 438
468 std::string result = "Must be called on "; 439 std::string result = "Must be called on ";
469 result += GetThreadName(expected); 440 result += GetThreadName(expected);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 AtomicWord* storage = reinterpret_cast<AtomicWord*>( 553 AtomicWord* storage = reinterpret_cast<AtomicWord*>(
583 &globals.thread_delegates[identifier]); 554 &globals.thread_delegates[identifier]);
584 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( 555 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
585 storage, reinterpret_cast<AtomicWord>(delegate)); 556 storage, reinterpret_cast<AtomicWord>(delegate));
586 557
587 // This catches registration when previously registered. 558 // This catches registration when previously registered.
588 DCHECK(!delegate || !old_pointer); 559 DCHECK(!delegate || !old_pointer);
589 } 560 }
590 561
591 } // namespace content 562 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/browser_thread_impl.h ('k') | content/browser/browser_thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698