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.
5 #include "components/domain_reliability/dispatcher.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "base/timer/timer.h"
11 #include "components/domain_reliability/util.h"
13 namespace domain_reliability {
15 struct DomainReliabilityDispatcher::Task {
16 Task(const base::Closure& closure,
17 scoped_ptr<MockableTime::Timer> timer,
18 base::TimeDelta min_delay,
19 base::TimeDelta max_delay);
22 base::Closure closure;
23 scoped_ptr<MockableTime::Timer> timer;
24 base::TimeDelta min_delay;
25 base::TimeDelta max_delay;
29 DomainReliabilityDispatcher::Task::Task(const base::Closure& closure,
30 scoped_ptr<MockableTime::Timer> timer,
31 base::TimeDelta min_delay,
32 base::TimeDelta max_delay)
39 DomainReliabilityDispatcher::Task::~Task() {}
41 DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
44 DomainReliabilityDispatcher::~DomainReliabilityDispatcher() {
45 // TODO(ttuttle): STLElementDeleter?
46 STLDeleteElements(&tasks_);
49 void DomainReliabilityDispatcher::ScheduleTask(
50 const base::Closure& closure,
51 base::TimeDelta min_delay,
52 base::TimeDelta max_delay) {
53 DCHECK(!closure.is_null());
54 // Would be DCHECK_LE, but you can't << a TimeDelta.
55 DCHECK(min_delay <= max_delay);
57 Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay);
59 if (max_delay.InMicroseconds() < 0)
60 RunAndDeleteTask(task);
61 else if (min_delay.InMicroseconds() < 0)
62 MakeTaskEligible(task);
64 MakeTaskWaiting(task);
67 void DomainReliabilityDispatcher::RunEligibleTasks() {
68 // Move all eligible tasks to a separate set so that eligible_tasks_.erase in
69 // RunAndDeleteTask won't erase elements out from under the iterator. (Also
70 // keeps RunEligibleTasks from running forever if a task adds a new, already-
71 // eligible task that does the same, and so on.)
72 std::set<Task*> tasks;
73 tasks.swap(eligible_tasks_);
75 for (std::set<Task*>::const_iterator it = tasks.begin();
80 DCHECK(task->eligible);
81 RunAndDeleteTask(task);
85 void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
87 DCHECK(!task->eligible);
88 DCHECK(!task->timer->IsRunning());
89 task->timer->Start(FROM_HERE,
91 base::Bind(&DomainReliabilityDispatcher::MakeTaskEligible,
92 base::Unretained(this),
97 DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
99 DCHECK(!task->eligible);
100 task->eligible = true;
101 eligible_tasks_.insert(task);
102 task->timer->Start(FROM_HERE,
103 task->max_delay - task->min_delay,
104 base::Bind(&DomainReliabilityDispatcher::RunAndDeleteTask,
105 base::Unretained(this),
109 void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
111 DCHECK(!task->closure.is_null());
114 eligible_tasks_.erase(task);
119 } // namespace domain_reliability