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

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

Issue 2168093002: Reorganizing few DCHECKs for better catching of failure. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 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
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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 // during shutdown get run. There's nothing particularly scientific about the 151 // during shutdown get run. There's nothing particularly scientific about the
152 // number chosen. 152 // number chosen.
153 const int kMaxNewShutdownBlockingTasks = 1000; 153 const int kMaxNewShutdownBlockingTasks = 1000;
154 BrowserThreadGlobals& globals = g_globals.Get(); 154 BrowserThreadGlobals& globals = g_globals.Get();
155 globals.blocking_pool->Shutdown(kMaxNewShutdownBlockingTasks); 155 globals.blocking_pool->Shutdown(kMaxNewShutdownBlockingTasks);
156 } 156 }
157 157
158 // static 158 // static
159 void BrowserThreadImpl::FlushThreadPoolHelperForTesting() { 159 void BrowserThreadImpl::FlushThreadPoolHelperForTesting() {
160 // We don't want to create a pool if none exists. 160 // We don't want to create a pool if none exists.
161 if (g_globals == NULL) 161 if (g_globals == nullptr)
162 return; 162 return;
163 g_globals.Get().blocking_pool->FlushForTesting(); 163 g_globals.Get().blocking_pool->FlushForTesting();
164 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting(); 164 disk_cache::SimpleBackendImpl::FlushWorkerPoolForTesting();
165 } 165 }
166 166
167 void BrowserThreadImpl::Init() { 167 void BrowserThreadImpl::Init() {
168 BrowserThreadGlobals& globals = g_globals.Get(); 168 BrowserThreadGlobals& globals = g_globals.Get();
169 169
170 using base::subtle::AtomicWord; 170 using base::subtle::AtomicWord;
171 AtomicWord* storage = 171 AtomicWord* storage =
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer); 279 reinterpret_cast<BrowserThreadDelegate*>(stored_pointer);
280 280
281 if (delegate) 281 if (delegate)
282 delegate->CleanUp(); 282 delegate->CleanUp();
283 283
284 // PostTaskHelper() accesses the message loop while holding this lock. 284 // PostTaskHelper() accesses the message loop while holding this lock.
285 // However, the message loop will soon be destructed without any locking. So 285 // However, the message loop will soon be destructed without any locking. So
286 // to prevent a race with accessing the message loop in PostTaskHelper(), 286 // to prevent a race with accessing the message loop in PostTaskHelper(),
287 // remove this thread from the global array now. 287 // remove this thread from the global array now.
288 base::AutoLock lock(globals.lock); 288 base::AutoLock lock(globals.lock);
289 globals.threads[identifier_] = NULL; 289 globals.threads[identifier_] = nullptr;
290 } 290 }
291 291
292 void BrowserThreadImpl::Initialize() { 292 void BrowserThreadImpl::Initialize() {
293 BrowserThreadGlobals& globals = g_globals.Get(); 293 BrowserThreadGlobals& globals = g_globals.Get();
294 294
295 base::AutoLock lock(globals.lock); 295 base::AutoLock lock(globals.lock);
296 DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT); 296 DCHECK(identifier_ >= 0);
no sievers 2016/07/21 19:08:01 nit: you can even do DCHECK_GE(identifier, 0) whic
AKV 2016/07/22 14:26:13 Done. Thanks, that's very helpful in catching fail
297 DCHECK(globals.threads[identifier_] == NULL); 297 DCHECK(identifier_ < ID_COUNT);
298 DCHECK(globals.threads[identifier_] == nullptr);
298 globals.threads[identifier_] = this; 299 globals.threads[identifier_] = this;
299 } 300 }
300 301
301 BrowserThreadImpl::~BrowserThreadImpl() { 302 BrowserThreadImpl::~BrowserThreadImpl() {
302 // All Thread subclasses must call Stop() in the destructor. This is 303 // All Thread subclasses must call Stop() in the destructor. This is
303 // doubly important here as various bits of code check they are on 304 // doubly important here as various bits of code check they are on
304 // the right BrowserThread. 305 // the right BrowserThread.
305 Stop(); 306 Stop();
306 307
307 BrowserThreadGlobals& globals = g_globals.Get(); 308 BrowserThreadGlobals& globals = g_globals.Get();
308 base::AutoLock lock(globals.lock); 309 base::AutoLock lock(globals.lock);
309 globals.threads[identifier_] = NULL; 310 globals.threads[identifier_] = nullptr;
310 #ifndef NDEBUG 311 #ifndef NDEBUG
311 // Double check that the threads are ordered correctly in the enumeration. 312 // Double check that the threads are ordered correctly in the enumeration.
312 for (int i = identifier_ + 1; i < ID_COUNT; ++i) { 313 for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
313 DCHECK(!globals.threads[i]) << 314 DCHECK(!globals.threads[i]) <<
314 "Threads must be listed in the reverse order that they die"; 315 "Threads must be listed in the reverse order that they die";
315 } 316 }
316 #endif 317 #endif
317 } 318 }
318 319
319 bool BrowserThreadImpl::StartWithOptions(const Options& options) { 320 bool BrowserThreadImpl::StartWithOptions(const Options& options) {
320 // 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
321 // starting, as the new thread can asynchronously start touching the 322 // starting, as the new thread can asynchronously start touching the
322 // table (and other thread's message_loop). 323 // table (and other thread's message_loop).
323 BrowserThreadGlobals& globals = g_globals.Get(); 324 BrowserThreadGlobals& globals = g_globals.Get();
324 base::AutoLock lock(globals.lock); 325 base::AutoLock lock(globals.lock);
325 return Thread::StartWithOptions(options); 326 return Thread::StartWithOptions(options);
326 } 327 }
327 328
328 // static 329 // static
329 bool BrowserThreadImpl::PostTaskHelper( 330 bool BrowserThreadImpl::PostTaskHelper(
330 BrowserThread::ID identifier, 331 BrowserThread::ID identifier,
331 const tracked_objects::Location& from_here, 332 const tracked_objects::Location& from_here,
332 const base::Closure& task, 333 const base::Closure& task,
333 base::TimeDelta delay, 334 base::TimeDelta delay,
334 bool nestable) { 335 bool nestable) {
335 DCHECK(identifier >= 0 && identifier < ID_COUNT); 336 DCHECK(identifier >= 0);
337 DCHECK(identifier < ID_COUNT);
336 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in 338 // Optimization: to avoid unnecessary locks, we listed the ID enumeration in
337 // order of lifetime. So no need to lock if we know that the target thread 339 // order of lifetime. So no need to lock if we know that the target thread
338 // outlives current thread. 340 // outlives current thread.
339 // Note: since the array is so small, ok to loop instead of creating a map, 341 // Note: since the array is so small, ok to loop instead of creating a map,
340 // which would require a lock because std::map isn't thread safe, defeating 342 // which would require a lock because std::map isn't thread safe, defeating
341 // the whole purpose of this optimization. 343 // the whole purpose of this optimization.
342 BrowserThread::ID current_thread = ID_COUNT; 344 BrowserThread::ID current_thread = ID_COUNT;
343 bool target_thread_outlives_current = 345 bool target_thread_outlives_current =
344 GetCurrentThreadIdentifier(&current_thread) && 346 GetCurrentThreadIdentifier(&current_thread) &&
345 current_thread >= identifier; 347 current_thread >= identifier;
346 348
347 BrowserThreadGlobals& globals = g_globals.Get(); 349 BrowserThreadGlobals& globals = g_globals.Get();
348 if (!target_thread_outlives_current) 350 if (!target_thread_outlives_current)
349 globals.lock.Acquire(); 351 globals.lock.Acquire();
350 352
351 base::MessageLoop* message_loop = 353 base::MessageLoop* message_loop =
352 globals.threads[identifier] ? globals.threads[identifier]->message_loop() 354 globals.threads[identifier] ? globals.threads[identifier]->message_loop()
353 : NULL; 355 : nullptr;
354 if (message_loop) { 356 if (message_loop) {
355 if (nestable) { 357 if (nestable) {
356 message_loop->task_runner()->PostDelayedTask(from_here, task, delay); 358 message_loop->task_runner()->PostDelayedTask(from_here, task, delay);
357 } else { 359 } else {
358 message_loop->task_runner()->PostNonNestableDelayedTask(from_here, task, 360 message_loop->task_runner()->PostNonNestableDelayedTask(from_here, task,
359 delay); 361 delay);
360 } 362 }
361 } 363 }
362 364
363 if (!target_thread_outlives_current) 365 if (!target_thread_outlives_current)
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 task); 402 task);
401 } 403 }
402 404
403 // static 405 // static
404 base::SequencedWorkerPool* BrowserThread::GetBlockingPool() { 406 base::SequencedWorkerPool* BrowserThread::GetBlockingPool() {
405 return g_globals.Get().blocking_pool.get(); 407 return g_globals.Get().blocking_pool.get();
406 } 408 }
407 409
408 // static 410 // static
409 bool BrowserThread::IsThreadInitialized(ID identifier) { 411 bool BrowserThread::IsThreadInitialized(ID identifier) {
410 if (g_globals == NULL) 412 if (g_globals == nullptr)
411 return false; 413 return false;
412 414
413 BrowserThreadGlobals& globals = g_globals.Get(); 415 BrowserThreadGlobals& globals = g_globals.Get();
414 base::AutoLock lock(globals.lock); 416 base::AutoLock lock(globals.lock);
415 DCHECK(identifier >= 0 && identifier < ID_COUNT); 417 DCHECK(identifier >= 0);
416 return globals.threads[identifier] != NULL; 418 DCHECK(identifier < ID_COUNT);
419 return globals.threads[identifier] != nullptr;
417 } 420 }
418 421
419 // static 422 // static
420 bool BrowserThread::CurrentlyOn(ID identifier) { 423 bool BrowserThread::CurrentlyOn(ID identifier) {
421 BrowserThreadGlobals& globals = g_globals.Get(); 424 BrowserThreadGlobals& globals = g_globals.Get();
422 base::AutoLock lock(globals.lock); 425 base::AutoLock lock(globals.lock);
423 DCHECK(identifier >= 0 && identifier < ID_COUNT); 426 DCHECK(identifier >= 0);
427 DCHECK(identifier < ID_COUNT);
424 return globals.threads[identifier] && 428 return globals.threads[identifier] &&
425 globals.threads[identifier]->message_loop() == 429 globals.threads[identifier]->message_loop() ==
426 base::MessageLoop::current(); 430 base::MessageLoop::current();
427 } 431 }
428 432
429 // static 433 // static
430 std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) { 434 std::string BrowserThread::GetDCheckCurrentlyOnErrorMessage(ID expected) {
431 std::string actual_name = base::PlatformThread::GetName(); 435 std::string actual_name = base::PlatformThread::GetName();
432 if (actual_name.empty()) 436 if (actual_name.empty())
433 actual_name = "Unknown Thread"; 437 actual_name = "Unknown Thread";
434 438
435 std::string result = "Must be called on "; 439 std::string result = "Must be called on ";
436 result += GetThreadName(expected); 440 result += GetThreadName(expected);
437 result += "; actually called on "; 441 result += "; actually called on ";
438 result += actual_name; 442 result += actual_name;
439 result += "."; 443 result += ".";
440 return result; 444 return result;
441 } 445 }
442 446
443 // static 447 // static
444 bool BrowserThread::IsMessageLoopValid(ID identifier) { 448 bool BrowserThread::IsMessageLoopValid(ID identifier) {
445 if (g_globals == NULL) 449 if (g_globals == nullptr)
446 return false; 450 return false;
447 451
448 BrowserThreadGlobals& globals = g_globals.Get(); 452 BrowserThreadGlobals& globals = g_globals.Get();
449 base::AutoLock lock(globals.lock); 453 base::AutoLock lock(globals.lock);
450 DCHECK(identifier >= 0 && identifier < ID_COUNT); 454 DCHECK(identifier >= 0);
455 DCHECK(identifier < ID_COUNT);
451 return globals.threads[identifier] && 456 return globals.threads[identifier] &&
452 globals.threads[identifier]->message_loop(); 457 globals.threads[identifier]->message_loop();
453 } 458 }
454 459
455 // static 460 // static
456 bool BrowserThread::PostTask(ID identifier, 461 bool BrowserThread::PostTask(ID identifier,
457 const tracked_objects::Location& from_here, 462 const tracked_objects::Location& from_here,
458 const base::Closure& task) { 463 const base::Closure& task) {
459 return BrowserThreadImpl::PostTaskHelper( 464 return BrowserThreadImpl::PostTaskHelper(
460 identifier, from_here, task, base::TimeDelta(), true); 465 identifier, from_here, task, base::TimeDelta(), true);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 ID identifier, 498 ID identifier,
494 const tracked_objects::Location& from_here, 499 const tracked_objects::Location& from_here,
495 const base::Closure& task, 500 const base::Closure& task,
496 const base::Closure& reply) { 501 const base::Closure& reply) {
497 return GetTaskRunnerForThread(identifier) 502 return GetTaskRunnerForThread(identifier)
498 ->PostTaskAndReply(from_here, task, reply); 503 ->PostTaskAndReply(from_here, task, reply);
499 } 504 }
500 505
501 // static 506 // static
502 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) { 507 bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
503 if (g_globals == NULL) 508 if (g_globals == nullptr)
504 return false; 509 return false;
505 510
506 base::MessageLoop* cur_message_loop = base::MessageLoop::current(); 511 base::MessageLoop* cur_message_loop = base::MessageLoop::current();
507 BrowserThreadGlobals& globals = g_globals.Get(); 512 BrowserThreadGlobals& globals = g_globals.Get();
508 // Profiler to track potential contention on |globals.lock|. This only does 513 // Profiler to track potential contention on |globals.lock|. This only does
509 // real work on canary and local dev builds, so the cost of having this here 514 // real work on canary and local dev builds, so the cost of having this here
510 // should be minimal. 515 // should be minimal.
511 tracked_objects::ScopedTracker tracking_profile(FROM_HERE); 516 tracked_objects::ScopedTracker tracking_profile(FROM_HERE);
512 base::AutoLock lock(globals.lock); 517 base::AutoLock lock(globals.lock);
513 for (int i = 0; i < ID_COUNT; ++i) { 518 for (int i = 0; i < ID_COUNT; ++i) {
514 if (globals.threads[i] && 519 if (globals.threads[i] &&
515 globals.threads[i]->message_loop() == cur_message_loop) { 520 globals.threads[i]->message_loop() == cur_message_loop) {
516 *identifier = globals.threads[i]->identifier_; 521 *identifier = globals.threads[i]->identifier_;
517 return true; 522 return true;
518 } 523 }
519 } 524 }
520 525
521 return false; 526 return false;
522 } 527 }
523 528
524 // static 529 // static
525 scoped_refptr<base::SingleThreadTaskRunner> 530 scoped_refptr<base::SingleThreadTaskRunner>
526 BrowserThread::GetTaskRunnerForThread(ID identifier) { 531 BrowserThread::GetTaskRunnerForThread(ID identifier) {
527 return g_task_runners.Get().proxies[identifier]; 532 return g_task_runners.Get().proxies[identifier];
528 } 533 }
529 534
530 // static 535 // static
531 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) { 536 base::MessageLoop* BrowserThread::UnsafeGetMessageLoopForThread(ID identifier) {
532 if (g_globals == NULL) 537 if (g_globals == nullptr)
533 return NULL; 538 return nullptr;
534 539
535 BrowserThreadGlobals& globals = g_globals.Get(); 540 BrowserThreadGlobals& globals = g_globals.Get();
536 base::AutoLock lock(globals.lock); 541 base::AutoLock lock(globals.lock);
537 base::Thread* thread = globals.threads[identifier]; 542 base::Thread* thread = globals.threads[identifier];
538 DCHECK(thread); 543 DCHECK(thread);
539 base::MessageLoop* loop = thread->message_loop(); 544 base::MessageLoop* loop = thread->message_loop();
540 return loop; 545 return loop;
541 } 546 }
542 547
543 // static 548 // static
544 void BrowserThread::SetDelegate(ID identifier, 549 void BrowserThread::SetDelegate(ID identifier,
545 BrowserThreadDelegate* delegate) { 550 BrowserThreadDelegate* delegate) {
546 using base::subtle::AtomicWord; 551 using base::subtle::AtomicWord;
547 BrowserThreadGlobals& globals = g_globals.Get(); 552 BrowserThreadGlobals& globals = g_globals.Get();
548 AtomicWord* storage = reinterpret_cast<AtomicWord*>( 553 AtomicWord* storage = reinterpret_cast<AtomicWord*>(
549 &globals.thread_delegates[identifier]); 554 &globals.thread_delegates[identifier]);
550 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange( 555 AtomicWord old_pointer = base::subtle::NoBarrier_AtomicExchange(
551 storage, reinterpret_cast<AtomicWord>(delegate)); 556 storage, reinterpret_cast<AtomicWord>(delegate));
552 557
553 // This catches registration when previously registered. 558 // This catches registration when previously registered.
554 DCHECK(!delegate || !old_pointer); 559 DCHECK(!delegate);
560 DCHECK(!old_pointer);
no sievers 2016/07/21 19:08:01 This is wrong. The current code basically checks t
AKV 2016/07/22 14:26:13 Done. Thanks.
555 } 561 }
556 562
557 } // namespace content 563 } // namespace content
OLDNEW
« no previous file with comments | « no previous file | content/browser/download/save_item.cc » ('j') | content/browser/download/save_item.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698