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 |