Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" | 5 #include "base/task_scheduler/scheduler_single_thread_task_runner_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/callback.h" | 13 #include "base/callback.h" |
| 14 #include "base/debug/stack_trace.h" | |
| 14 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
| 15 #include "base/single_thread_task_runner.h" | 16 #include "base/single_thread_task_runner.h" |
| 16 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 17 #include "base/synchronization/atomic_flag.h" | 18 #include "base/synchronization/atomic_flag.h" |
| 18 #include "base/task_scheduler/delayed_task_manager.h" | 19 #include "base/task_scheduler/delayed_task_manager.h" |
| 19 #include "base/task_scheduler/scheduler_worker.h" | 20 #include "base/task_scheduler/scheduler_worker.h" |
| 20 #include "base/task_scheduler/sequence.h" | 21 #include "base/task_scheduler/sequence.h" |
| 21 #include "base/task_scheduler/task.h" | 22 #include "base/task_scheduler/task.h" |
| 22 #include "base/task_scheduler/task_tracker.h" | 23 #include "base/task_scheduler/task_tracker.h" |
| 23 #include "base/task_scheduler/task_traits.h" | 24 #include "base/task_scheduler/task_traits.h" |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 // Tasks are never nested within the task scheduler. | 278 // Tasks are never nested within the task scheduler. |
| 278 return PostDelayedTask(from_here, std::move(closure), delay); | 279 return PostDelayedTask(from_here, std::move(closure), delay); |
| 279 } | 280 } |
| 280 | 281 |
| 281 bool RunsTasksOnCurrentThread() const override { | 282 bool RunsTasksOnCurrentThread() const override { |
| 282 return GetDelegate()->RunsTasksOnCurrentThread(); | 283 return GetDelegate()->RunsTasksOnCurrentThread(); |
| 283 } | 284 } |
| 284 | 285 |
| 285 private: | 286 private: |
| 286 ~SchedulerSingleThreadTaskRunner() override { | 287 ~SchedulerSingleThreadTaskRunner() override { |
| 288 // Note: this will crash if SchedulerSingleThreadTaskRunnerManager() is | |
|
robliao
2017/05/04 21:54:27
Nit: Capitalize 'this'
Nit: No () as we're talking
gab
2017/05/04 22:27:41
Done.
| |
| 289 // incorrectly destroyed first in tests (in production the TaskScheduler and | |
| 290 // all of its state are intentionally leaked after | |
| 291 // TaskScheduler::Shutdown(). See ~SchedulerSingleThreadTaskRunnerManager() | |
| 292 // for more details. | |
| 287 outer_->UnregisterSchedulerWorker(worker_); | 293 outer_->UnregisterSchedulerWorker(worker_); |
| 288 } | 294 } |
| 289 | 295 |
| 290 void PostTaskNow(std::unique_ptr<Task> task) { | 296 void PostTaskNow(std::unique_ptr<Task> task) { |
| 291 scoped_refptr<Sequence> sequence = GetDelegate()->sequence(); | 297 scoped_refptr<Sequence> sequence = GetDelegate()->sequence(); |
| 292 // If |sequence| is null, then the thread is effectively gone (either | 298 // If |sequence| is null, then the thread is effectively gone (either |
| 293 // shutdown or joined). | 299 // shutdown or joined). |
| 294 if (!sequence) | 300 if (!sequence) |
| 295 return; | 301 return; |
| 296 | 302 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 318 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) { | 324 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) { |
| 319 DCHECK(task_tracker_); | 325 DCHECK(task_tracker_); |
| 320 DCHECK(delayed_task_manager_); | 326 DCHECK(delayed_task_manager_); |
| 321 } | 327 } |
| 322 | 328 |
| 323 SchedulerSingleThreadTaskRunnerManager:: | 329 SchedulerSingleThreadTaskRunnerManager:: |
| 324 ~SchedulerSingleThreadTaskRunnerManager() { | 330 ~SchedulerSingleThreadTaskRunnerManager() { |
| 325 #if DCHECK_IS_ON() | 331 #if DCHECK_IS_ON() |
| 326 size_t workers_unregistered_during_join = | 332 size_t workers_unregistered_during_join = |
| 327 subtle::NoBarrier_Load(&workers_unregistered_during_join_); | 333 subtle::NoBarrier_Load(&workers_unregistered_during_join_); |
| 328 DCHECK_EQ(workers_unregistered_during_join, workers_.size()) | 334 // Log an ERROR instead of DCHECK'ing as it's often useful to have both the |
| 329 << "There cannot be outstanding SingleThreadTaskRunners upon destruction " | 335 // stack trace of this call and the crash stack trace of the upcoming |
| 330 "of SchedulerSingleThreadTaskRunnerManager or the Task Scheduler"; | 336 // out-of-order ~SchedulerSingleThreadTaskRunner() call to know what to flip. |
| 337 DLOG_IF(ERROR, workers_unregistered_during_join != workers_.size()) | |
| 338 << "Expect incoming crash in ~SchedulerSingleThreadTaskRunner()!!! There " | |
| 339 "cannot be outstanding SingleThreadTaskRunners upon destruction " | |
| 340 "of SchedulerSingleThreadTaskRunnerManager in tests " | |
| 341 << workers_.size() - workers_unregistered_during_join << " outstanding). " | |
| 342 << "Hint: If you're hitting this it's most likely because your test " | |
|
robliao
2017/05/04 21:54:28
s/Hint/Hint 1/
gab
2017/05/04 22:27:41
Done.
| |
| 343 "fixture is destroying its TaskScheduler too early (e.g. via " | |
| 344 "~base::test::ScopedTaskEnvironment() or " | |
|
robliao
2017/05/04 21:54:27
Nit: base::test::~ScopedTaskEnvironment() and cont
gab
2017/05/04 22:27:41
Done.
| |
| 345 "~content::TestBrowserThreadBundle()). Refer to the following stack " | |
| 346 "trace to know what caused this destruction as well as to the " | |
| 347 "upcoming crash in ~SchedulerSingleThreadTaskRunner() to know what " | |
| 348 "should have happened before. " | |
| 349 "Hint hint: base::test::ScopedTaskEnvironment et al. should typically " | |
|
robliao
2017/05/04 21:54:27
s/Hint hint/Hint 2/
gab
2017/05/04 22:27:41
Done.
| |
| 350 "be the first member in a test fixture to ensure it's initialized " | |
| 351 "first and destroyed last.\n" | |
| 352 << base::debug::StackTrace().ToString(); | |
| 331 #endif | 353 #endif |
| 332 } | 354 } |
| 333 | 355 |
| 334 void SchedulerSingleThreadTaskRunnerManager::Start() { | 356 void SchedulerSingleThreadTaskRunnerManager::Start() { |
| 335 decltype(workers_) workers_to_start; | 357 decltype(workers_) workers_to_start; |
| 336 { | 358 { |
| 337 AutoSchedulerLock auto_lock(lock_); | 359 AutoSchedulerLock auto_lock(lock_); |
| 338 started_ = true; | 360 started_ = true; |
| 339 workers_to_start = workers_; | 361 workers_to_start = workers_; |
| 340 } | 362 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 }); | 484 }); |
| 463 DCHECK(worker_iter != workers_.end()); | 485 DCHECK(worker_iter != workers_.end()); |
| 464 worker_to_destroy = std::move(*worker_iter); | 486 worker_to_destroy = std::move(*worker_iter); |
| 465 workers_.erase(worker_iter); | 487 workers_.erase(worker_iter); |
| 466 } | 488 } |
| 467 worker_to_destroy->Cleanup(); | 489 worker_to_destroy->Cleanup(); |
| 468 } | 490 } |
| 469 | 491 |
| 470 } // namespace internal | 492 } // namespace internal |
| 471 } // namespace base | 493 } // namespace base |
| OLD | NEW |