dispatcher.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/domain_reliability/dispatcher.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback.h"
  9. #include "base/timer/timer.h"
  10. #include "components/domain_reliability/util.h"
  11. namespace domain_reliability {
  12. struct DomainReliabilityDispatcher::Task {
  13. Task(base::OnceClosure closure,
  14. std::unique_ptr<MockableTime::Timer> timer,
  15. base::TimeDelta min_delay,
  16. base::TimeDelta max_delay);
  17. Task(Task&& other);
  18. Task& operator=(Task&& other);
  19. ~Task();
  20. base::OnceClosure closure;
  21. std::unique_ptr<MockableTime::Timer> timer;
  22. base::TimeDelta min_delay;
  23. base::TimeDelta max_delay;
  24. bool eligible;
  25. };
  26. DomainReliabilityDispatcher::Task::Task(
  27. base::OnceClosure closure,
  28. std::unique_ptr<MockableTime::Timer> timer,
  29. base::TimeDelta min_delay,
  30. base::TimeDelta max_delay)
  31. : closure(std::move(closure)),
  32. timer(std::move(timer)),
  33. min_delay(min_delay),
  34. max_delay(max_delay),
  35. eligible(false) {}
  36. DomainReliabilityDispatcher::Task::Task(Task&& other) = default;
  37. DomainReliabilityDispatcher::Task& DomainReliabilityDispatcher::Task::operator=(
  38. Task&& other) = default;
  39. DomainReliabilityDispatcher::Task::~Task() = default;
  40. DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
  41. : time_(time) {}
  42. DomainReliabilityDispatcher::~DomainReliabilityDispatcher() = default;
  43. void DomainReliabilityDispatcher::ScheduleTask(base::OnceClosure closure,
  44. base::TimeDelta min_delay,
  45. base::TimeDelta max_delay) {
  46. DCHECK(closure);
  47. // Would be DCHECK_LE, but you can't << a TimeDelta.
  48. DCHECK(min_delay <= max_delay);
  49. std::unique_ptr<Task> owned_task = std::make_unique<Task>(
  50. std::move(closure), time_->CreateTimer(), min_delay, max_delay);
  51. Task* task = owned_task.get();
  52. tasks_.insert(std::move(owned_task));
  53. if (max_delay.InMicroseconds() < 0)
  54. RunAndDeleteTask(task);
  55. else if (min_delay.InMicroseconds() < 0)
  56. MakeTaskEligible(task);
  57. else
  58. MakeTaskWaiting(task);
  59. }
  60. void DomainReliabilityDispatcher::RunEligibleTasks() {
  61. // Move all eligible tasks to a separate set so that eligible_tasks_.erase in
  62. // RunAndDeleteTask won't erase elements out from under the iterator. (Also
  63. // keeps RunEligibleTasks from running forever if a task adds a new, already-
  64. // eligible task that does the same, and so on.)
  65. std::set<Task*> tasks;
  66. tasks.swap(eligible_tasks_);
  67. for (auto* task : tasks) {
  68. DCHECK(task);
  69. DCHECK(task->eligible);
  70. RunAndDeleteTask(task);
  71. }
  72. }
  73. void DomainReliabilityDispatcher::RunAllTasksForTesting() {
  74. std::set<Task*> tasks;
  75. for (auto& task : tasks_)
  76. tasks.insert(task.get());
  77. for (auto* task : tasks) {
  78. DCHECK(task);
  79. RunAndDeleteTask(task);
  80. }
  81. }
  82. void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
  83. DCHECK(task);
  84. DCHECK(!task->eligible);
  85. DCHECK(!task->timer->IsRunning());
  86. task->timer->Start(
  87. FROM_HERE, task->min_delay,
  88. base::BindOnce(&DomainReliabilityDispatcher::MakeTaskEligible,
  89. base::Unretained(this), task));
  90. }
  91. void
  92. DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
  93. DCHECK(task);
  94. DCHECK(!task->eligible);
  95. task->eligible = true;
  96. eligible_tasks_.insert(task);
  97. task->timer->Start(
  98. FROM_HERE, task->max_delay - task->min_delay,
  99. base::BindOnce(&DomainReliabilityDispatcher::RunAndDeleteTask,
  100. base::Unretained(this), task));
  101. }
  102. void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
  103. DCHECK(task);
  104. DCHECK(task->closure);
  105. std::move(task->closure).Run();
  106. if (task->eligible)
  107. eligible_tasks_.erase(task);
  108. auto it = tasks_.find(task);
  109. DCHECK(it != tasks_.end());
  110. tasks_.erase(it);
  111. }
  112. } // namespace domain_reliability