Fix UnlockEndpointIsDelayed again.
[chromium-blink-merge.git] / components / domain_reliability / dispatcher.cc
blobc02fe27be32bc6c9430b6107336be6f956450f2f
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"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/stl_util.h"
11 #include "base/timer/timer.h"
12 #include "components/domain_reliability/util.h"
14 namespace domain_reliability {
16 struct DomainReliabilityDispatcher::Task {
17 Task(const base::Closure& closure,
18 scoped_ptr<MockableTime::Timer> timer,
19 base::TimeDelta min_delay,
20 base::TimeDelta max_delay);
21 ~Task();
23 base::Closure closure;
24 scoped_ptr<MockableTime::Timer> timer;
25 base::TimeDelta min_delay;
26 base::TimeDelta max_delay;
27 bool eligible;
30 DomainReliabilityDispatcher::Task::Task(const base::Closure& closure,
31 scoped_ptr<MockableTime::Timer> timer,
32 base::TimeDelta min_delay,
33 base::TimeDelta max_delay)
34 : closure(closure),
35 timer(timer.Pass()),
36 min_delay(min_delay),
37 max_delay(max_delay),
38 eligible(false) {}
40 DomainReliabilityDispatcher::Task::~Task() {}
42 DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
43 : time_(time) {}
45 DomainReliabilityDispatcher::~DomainReliabilityDispatcher() {
46 // TODO(ttuttle): STLElementDeleter?
47 STLDeleteElements(&tasks_);
50 void DomainReliabilityDispatcher::ScheduleTask(
51 const base::Closure& closure,
52 base::TimeDelta min_delay,
53 base::TimeDelta max_delay) {
54 DCHECK(!closure.is_null());
55 // Would be DCHECK_LE, but you can't << a TimeDelta.
56 DCHECK(min_delay <= max_delay);
58 Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay);
59 tasks_.insert(task);
60 if (max_delay.InMicroseconds() < 0)
61 RunAndDeleteTask(task);
62 else if (min_delay.InMicroseconds() < 0)
63 MakeTaskEligible(task);
64 else
65 MakeTaskWaiting(task);
68 void DomainReliabilityDispatcher::RunEligibleTasks() {
69 // Move all eligible tasks to a separate set so that eligible_tasks_.erase in
70 // RunAndDeleteTask won't erase elements out from under the iterator. (Also
71 // keeps RunEligibleTasks from running forever if a task adds a new, already-
72 // eligible task that does the same, and so on.)
73 std::set<Task*> tasks;
74 tasks.swap(eligible_tasks_);
76 for (std::set<Task*>::const_iterator it = tasks.begin();
77 it != tasks.end();
78 ++it) {
79 Task* task = *it;
80 DCHECK(task);
81 DCHECK(task->eligible);
82 RunAndDeleteTask(task);
86 void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
87 DCHECK(task);
88 DCHECK(!task->eligible);
89 DCHECK(!task->timer->IsRunning());
90 task->timer->Start(FROM_HERE,
91 task->min_delay,
92 base::Bind(&DomainReliabilityDispatcher::MakeTaskEligible,
93 base::Unretained(this),
94 task));
97 void
98 DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
99 DCHECK(task);
100 DCHECK(!task->eligible);
101 task->eligible = true;
102 eligible_tasks_.insert(task);
103 task->timer->Start(FROM_HERE,
104 task->max_delay - task->min_delay,
105 base::Bind(&DomainReliabilityDispatcher::RunAndDeleteTask,
106 base::Unretained(this),
107 task));
110 void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
111 DCHECK(task);
112 DCHECK(!task->closure.is_null());
113 task->closure.Run();
114 if (task->eligible)
115 eligible_tasks_.erase(task);
116 tasks_.erase(task);
117 delete task;
120 } // namespace domain_reliability