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> |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 OnceClosure closure, | 276 OnceClosure closure, |
| 277 TimeDelta delay) override { | 277 TimeDelta delay) override { |
| 278 // Tasks are never nested within the task scheduler. | 278 // Tasks are never nested within the task scheduler. |
| 279 return PostDelayedTask(from_here, std::move(closure), delay); | 279 return PostDelayedTask(from_here, std::move(closure), delay); |
| 280 } | 280 } |
| 281 | 281 |
| 282 bool RunsTasksInCurrentSequence() const override { | 282 bool RunsTasksInCurrentSequence() const override { |
| 283 return GetDelegate()->RunsTasksInCurrentSequence(); | 283 return GetDelegate()->RunsTasksInCurrentSequence(); |
| 284 } | 284 } |
| 285 | 285 |
| 286 // SchedulerSingleThreadTaskRunner: | |
|
fdoray
2017/05/24 13:25:45
Update comment. This isn't an override.
robliao
2017/05/24 18:28:32
The headers are not strictly used for overrides, b
| |
| 287 void Start() { worker_->Start(); } | |
| 288 | |
| 286 private: | 289 private: |
| 287 ~SchedulerSingleThreadTaskRunner() override { | 290 ~SchedulerSingleThreadTaskRunner() override { |
| 288 // Note: This will crash if SchedulerSingleThreadTaskRunnerManager is | 291 // Note: This will crash if SchedulerSingleThreadTaskRunnerManager is |
| 289 // incorrectly destroyed first in tests (in production the TaskScheduler and | 292 // incorrectly destroyed first in tests (in production the TaskScheduler and |
| 290 // all of its state are intentionally leaked after | 293 // all of its state are intentionally leaked after |
| 291 // TaskScheduler::Shutdown(). See ~SchedulerSingleThreadTaskRunnerManager() | 294 // TaskScheduler::Shutdown(). See ~SchedulerSingleThreadTaskRunnerManager() |
| 292 // for more details. | 295 // for more details. |
| 293 outer_->UnregisterSchedulerWorker(worker_); | 296 outer_->UnregisterSchedulerWorker(worker_); |
| 294 } | 297 } |
| 295 | 298 |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 317 | 320 |
| 318 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); | 321 DISALLOW_COPY_AND_ASSIGN(SchedulerSingleThreadTaskRunner); |
| 319 }; | 322 }; |
| 320 | 323 |
| 321 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager( | 324 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunnerManager( |
| 322 TaskTracker* task_tracker, | 325 TaskTracker* task_tracker, |
| 323 DelayedTaskManager* delayed_task_manager) | 326 DelayedTaskManager* delayed_task_manager) |
| 324 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) { | 327 : task_tracker_(task_tracker), delayed_task_manager_(delayed_task_manager) { |
| 325 DCHECK(task_tracker_); | 328 DCHECK(task_tracker_); |
| 326 DCHECK(delayed_task_manager_); | 329 DCHECK(delayed_task_manager_); |
| 330 static_assert( | |
| 331 arraysize(shared_task_runners_) == ENVIRONMENT_COUNT, | |
| 332 "The size of |shared_task_runners_| must match ENVIRONMENT_COUNT"); | |
| 333 #if defined(OS_WIN) | |
| 334 static_assert( | |
| 335 arraysize(shared_com_task_runners_) == arraysize(shared_task_runners_), | |
| 336 "The size of |shared_com_task_runners_| must match " | |
| 337 "|shared_task_runners_|"); | |
| 338 #endif // defined(OS_WIN) | |
| 327 } | 339 } |
| 328 | 340 |
| 329 SchedulerSingleThreadTaskRunnerManager:: | 341 SchedulerSingleThreadTaskRunnerManager:: |
| 330 ~SchedulerSingleThreadTaskRunnerManager() { | 342 ~SchedulerSingleThreadTaskRunnerManager() { |
| 331 #if DCHECK_IS_ON() | 343 #if DCHECK_IS_ON() |
| 332 size_t workers_unregistered_during_join = | 344 size_t workers_unregistered_during_join = |
| 333 subtle::NoBarrier_Load(&workers_unregistered_during_join_); | 345 subtle::NoBarrier_Load(&workers_unregistered_during_join_); |
| 334 // Log an ERROR instead of DCHECK'ing as it's often useful to have both the | 346 // Log an ERROR instead of DCHECK'ing as it's often useful to have both the |
| 335 // stack trace of this call and the crash stack trace of the upcoming | 347 // stack trace of this call and the crash stack trace of the upcoming |
| 336 // out-of-order ~SchedulerSingleThreadTaskRunner() call to know what to flip. | 348 // out-of-order ~SchedulerSingleThreadTaskRunner() call to know what to flip. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 // workers are started as they are created. | 380 // workers are started as they are created. |
| 369 for (scoped_refptr<SchedulerWorker> worker : workers_to_start) { | 381 for (scoped_refptr<SchedulerWorker> worker : workers_to_start) { |
| 370 worker->Start(); | 382 worker->Start(); |
| 371 worker->WakeUp(); | 383 worker->WakeUp(); |
| 372 } | 384 } |
| 373 } | 385 } |
| 374 | 386 |
| 375 scoped_refptr<SingleThreadTaskRunner> | 387 scoped_refptr<SingleThreadTaskRunner> |
| 376 SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits( | 388 SchedulerSingleThreadTaskRunnerManager::CreateSingleThreadTaskRunnerWithTraits( |
| 377 const std::string& name, | 389 const std::string& name, |
| 378 ThreadPriority priority_hint, | 390 ThreadPriority priority_hint, |
|
fdoray
2017/05/24 13:25:45
Now that this file includes "base/task_scheduler/e
robliao
2017/05/24 18:28:32
Done.
| |
| 379 const TaskTraits& traits) { | 391 const TaskTraits& traits, |
| 380 return CreateSingleThreadTaskRunnerWithDelegate<SchedulerWorkerDelegate>( | 392 SingleThreadTaskRunnerThreadMode thread_mode) { |
| 381 name, priority_hint, traits); | 393 return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerDelegate>( |
| 394 name, priority_hint, traits, thread_mode); | |
| 382 } | 395 } |
| 383 | 396 |
| 384 #if defined(OS_WIN) | 397 #if defined(OS_WIN) |
| 385 scoped_refptr<SingleThreadTaskRunner> | 398 scoped_refptr<SingleThreadTaskRunner> |
| 386 SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits( | 399 SchedulerSingleThreadTaskRunnerManager::CreateCOMSTATaskRunnerWithTraits( |
| 387 const std::string& name, | 400 const std::string& name, |
| 388 ThreadPriority priority_hint, | 401 ThreadPriority priority_hint, |
| 389 const TaskTraits& traits) { | 402 const TaskTraits& traits, |
| 390 return CreateSingleThreadTaskRunnerWithDelegate<SchedulerWorkerCOMDelegate>( | 403 SingleThreadTaskRunnerThreadMode thread_mode) { |
| 391 name, priority_hint, traits); | 404 return CreateTaskRunnerWithTraitsImpl<SchedulerWorkerCOMDelegate>( |
| 405 name, priority_hint, traits, thread_mode); | |
| 392 } | 406 } |
| 393 #endif // defined(OS_WIN) | 407 #endif // defined(OS_WIN) |
| 394 | 408 |
| 409 template <typename DelegateType> | |
| 410 scoped_refptr< | |
| 411 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner> | |
| 412 SchedulerSingleThreadTaskRunnerManager::CreateTaskRunnerWithTraitsImpl( | |
| 413 const std::string& name, | |
| 414 ThreadPriority priority_hint, | |
| 415 const TaskTraits& traits, | |
| 416 SingleThreadTaskRunnerThreadMode thread_mode) { | |
|
fdoray
2017/05/24 13:25:45
I would assert that WithBaseSyncPrimitives() is no
robliao
2017/05/24 18:28:32
Sounds reasonable to me. Done.
| |
| 417 // To simply the code, |dedicated_task_runner| is a local only variable that | |
|
fdoray
2017/05/24 13:25:45
To *simplify*
robliao
2017/05/24 18:28:32
Done.
| |
| 418 // allows the code to treat both the DEDICATED and SHARED cases similarly. In | |
| 419 // DEDICATED, the scoped_refptr is backed by a local variable and in SHARED, | |
| 420 // the scoped_refptr is backed by a member variable. | |
| 421 scoped_refptr<SchedulerSingleThreadTaskRunner> dedicated_task_runner; | |
| 422 scoped_refptr<SchedulerSingleThreadTaskRunner>& task_runner = | |
| 423 thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED | |
| 424 ? dedicated_task_runner | |
| 425 : GetSharedTaskRunnerForTraits<DelegateType>(traits); | |
| 426 bool new_task_runner = false; | |
| 427 bool started; | |
| 428 { | |
| 429 AutoSchedulerLock auto_lock(lock_); | |
| 430 if (!task_runner) { | |
| 431 std::string processed_name = | |
| 432 thread_mode == SingleThreadTaskRunnerThreadMode::DEDICATED | |
| 433 ? name | |
| 434 : "Shared" + name; | |
| 435 task_runner = CreateSingleThreadTaskRunnerWithDelegate<DelegateType>( | |
| 436 processed_name, priority_hint, traits); | |
|
fdoray
2017/05/24 13:25:45
Unfortunately, if someone creates a SingleThreadTa
robliao
2017/05/24 18:28:32
Nice catch. Fixed to reuse SchedulerWorkers.
| |
| 437 new_task_runner = true; | |
| 438 } | |
| 439 started = started_; | |
| 440 } | |
| 441 | |
| 442 if (new_task_runner && started) | |
| 443 task_runner->Start(); | |
|
fdoray
2017/05/24 13:25:45
What do you think of rewriting this method as:
te
robliao
2017/05/24 18:28:32
sgtm. Done.
| |
| 444 | |
| 445 return task_runner; | |
| 446 } | |
| 447 | |
| 395 void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() { | 448 void SchedulerSingleThreadTaskRunnerManager::JoinForTesting() { |
| 449 ReleaseSharedTaskRunners(); | |
|
fdoray
2017/05/24 13:25:45
Why is this needed? SchedulerWorker::JoinForTestin
robliao
2017/05/24 18:28:32
This is now ReleaseSharedSchedulerWorkers() and is
| |
| 450 | |
| 396 decltype(workers_) local_workers; | 451 decltype(workers_) local_workers; |
| 397 { | 452 { |
| 398 AutoSchedulerLock auto_lock(lock_); | 453 AutoSchedulerLock auto_lock(lock_); |
| 399 local_workers = std::move(workers_); | 454 local_workers = std::move(workers_); |
| 400 } | 455 } |
| 401 | 456 |
| 402 for (const auto& worker : local_workers) | 457 for (const auto& worker : local_workers) |
| 403 worker->JoinForTesting(); | 458 worker->JoinForTesting(); |
| 404 | 459 |
| 405 { | 460 { |
| 406 AutoSchedulerLock auto_lock(lock_); | 461 AutoSchedulerLock auto_lock(lock_); |
| 407 DCHECK(workers_.empty()) | 462 DCHECK(workers_.empty()) |
| 408 << "New worker(s) unexpectedly registered during join."; | 463 << "New worker(s) unexpectedly registered during join."; |
| 409 workers_ = std::move(local_workers); | 464 workers_ = std::move(local_workers); |
| 410 } | 465 } |
| 411 } | 466 } |
| 412 | 467 |
| 413 template <typename DelegateType> | 468 template <typename DelegateType> |
| 414 scoped_refptr<SingleThreadTaskRunner> SchedulerSingleThreadTaskRunnerManager:: | 469 scoped_refptr< |
| 470 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner> | |
| 471 SchedulerSingleThreadTaskRunnerManager:: | |
| 415 CreateSingleThreadTaskRunnerWithDelegate(const std::string& name, | 472 CreateSingleThreadTaskRunnerWithDelegate(const std::string& name, |
| 416 ThreadPriority priority_hint, | 473 ThreadPriority priority_hint, |
| 417 const TaskTraits& traits) { | 474 const TaskTraits& traits) { |
| 418 return new SchedulerSingleThreadTaskRunner( | 475 return new SchedulerSingleThreadTaskRunner( |
| 419 this, traits, | 476 this, traits, |
| 420 CreateAndRegisterSchedulerWorker<DelegateType>(name, priority_hint)); | 477 CreateAndRegisterSchedulerWorker<DelegateType>(name, priority_hint)); |
| 421 } | 478 } |
| 422 | 479 |
| 423 template <> | 480 template <> |
| 424 std::unique_ptr<SchedulerWorkerDelegate> | 481 std::unique_ptr<SchedulerWorkerDelegate> |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 437 StringPrintf("TaskSchedulerSingleThreadCOMSTA%s%d", name.c_str(), id), | 494 StringPrintf("TaskSchedulerSingleThreadCOMSTA%s%d", name.c_str(), id), |
| 438 task_tracker_); | 495 task_tracker_); |
| 439 } | 496 } |
| 440 #endif // defined(OS_WIN) | 497 #endif // defined(OS_WIN) |
| 441 | 498 |
| 442 template <typename DelegateType> | 499 template <typename DelegateType> |
| 443 SchedulerWorker* | 500 SchedulerWorker* |
| 444 SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( | 501 SchedulerSingleThreadTaskRunnerManager::CreateAndRegisterSchedulerWorker( |
| 445 const std::string& name, | 502 const std::string& name, |
| 446 ThreadPriority priority_hint) { | 503 ThreadPriority priority_hint) { |
| 447 SchedulerWorker* worker; | 504 lock_.AssertAcquired(); |
| 448 bool start_worker; | 505 int id = next_worker_id_++; |
| 506 workers_.emplace_back(make_scoped_refptr(new SchedulerWorker( | |
| 507 priority_hint, CreateSchedulerWorkerDelegate<DelegateType>(name, id), | |
| 508 task_tracker_))); | |
| 509 return workers_.back().get(); | |
| 510 } | |
| 449 | 511 |
| 450 { | 512 template <> |
| 451 AutoSchedulerLock auto_lock(lock_); | 513 scoped_refptr< |
| 452 int id = next_worker_id_++; | 514 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>& |
| 453 workers_.emplace_back(make_scoped_refptr(new SchedulerWorker( | 515 SchedulerSingleThreadTaskRunnerManager::GetSharedTaskRunnerForTraits< |
| 454 priority_hint, CreateSchedulerWorkerDelegate<DelegateType>(name, id), | 516 SchedulerWorkerDelegate>(const TaskTraits& traits) { |
| 455 task_tracker_))); | 517 return shared_task_runners_[GetEnvironmentIndexForTraits(traits)]; |
| 456 worker = workers_.back().get(); | 518 } |
| 457 start_worker = started_; | |
| 458 } | |
| 459 | 519 |
| 460 if (start_worker) | 520 #if defined(OS_WIN) |
| 461 worker->Start(); | 521 template <> |
| 462 | 522 scoped_refptr< |
| 463 return worker; | 523 SchedulerSingleThreadTaskRunnerManager::SchedulerSingleThreadTaskRunner>& |
| 524 SchedulerSingleThreadTaskRunnerManager::GetSharedTaskRunnerForTraits< | |
| 525 SchedulerWorkerCOMDelegate>(const TaskTraits& traits) { | |
| 526 return shared_com_task_runners_[GetEnvironmentIndexForTraits(traits)]; | |
| 464 } | 527 } |
| 528 #endif // defined(OS_WIN) | |
| 465 | 529 |
| 466 void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker( | 530 void SchedulerSingleThreadTaskRunnerManager::UnregisterSchedulerWorker( |
| 467 SchedulerWorker* worker) { | 531 SchedulerWorker* worker) { |
| 468 // Cleanup uses a SchedulerLock, so call Cleanup() after releasing | 532 // Cleanup uses a SchedulerLock, so call Cleanup() after releasing |
| 469 // |lock_|. | 533 // |lock_|. |
| 470 scoped_refptr<SchedulerWorker> worker_to_destroy; | 534 scoped_refptr<SchedulerWorker> worker_to_destroy; |
| 471 { | 535 { |
| 472 AutoSchedulerLock auto_lock(lock_); | 536 AutoSchedulerLock auto_lock(lock_); |
| 473 | 537 |
| 474 // We might be joining, so record that a worker was unregistered for | 538 // We might be joining, so record that a worker was unregistered for |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 485 [worker](const scoped_refptr<SchedulerWorker>& candidate) { | 549 [worker](const scoped_refptr<SchedulerWorker>& candidate) { |
| 486 return candidate.get() == worker; | 550 return candidate.get() == worker; |
| 487 }); | 551 }); |
| 488 DCHECK(worker_iter != workers_.end()); | 552 DCHECK(worker_iter != workers_.end()); |
| 489 worker_to_destroy = std::move(*worker_iter); | 553 worker_to_destroy = std::move(*worker_iter); |
| 490 workers_.erase(worker_iter); | 554 workers_.erase(worker_iter); |
| 491 } | 555 } |
| 492 worker_to_destroy->Cleanup(); | 556 worker_to_destroy->Cleanup(); |
| 493 } | 557 } |
| 494 | 558 |
| 559 void SchedulerSingleThreadTaskRunnerManager::ReleaseSharedTaskRunners() { | |
| 560 decltype(shared_task_runners_) local_shared_task_runners; | |
| 561 #if defined(OS_WIN) | |
| 562 decltype(shared_com_task_runners_) local_shared_com_task_runners; | |
| 563 #endif | |
| 564 { | |
| 565 AutoSchedulerLock auto_lock(lock_); | |
| 566 for (size_t i = 0; i < arraysize(shared_task_runners_); ++i) { | |
| 567 local_shared_task_runners[i] = std::move(shared_task_runners_[i]); | |
| 568 #if defined(OS_WIN) | |
| 569 local_shared_com_task_runners[i] = std::move(shared_com_task_runners_[i]); | |
| 570 #endif | |
| 571 } | |
| 572 } | |
| 573 } | |
| 574 | |
| 495 } // namespace internal | 575 } // namespace internal |
| 496 } // namespace base | 576 } // namespace base |
| OLD | NEW |