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 |