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/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
);
23 base::Closure closure
;
24 scoped_ptr
<MockableTime::Timer
> timer
;
25 base::TimeDelta min_delay
;
26 base::TimeDelta max_delay
;
30 DomainReliabilityDispatcher::Task::Task(const base::Closure
& closure
,
31 scoped_ptr
<MockableTime::Timer
> timer
,
32 base::TimeDelta min_delay
,
33 base::TimeDelta max_delay
)
40 DomainReliabilityDispatcher::Task::~Task() {}
42 DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime
* 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
);
60 if (max_delay
.InMicroseconds() < 0)
61 RunAndDeleteTask(task
);
62 else if (min_delay
.InMicroseconds() < 0)
63 MakeTaskEligible(task
);
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();
81 DCHECK(task
->eligible
);
82 RunAndDeleteTask(task
);
86 void DomainReliabilityDispatcher::MakeTaskWaiting(Task
* task
) {
88 DCHECK(!task
->eligible
);
89 DCHECK(!task
->timer
->IsRunning());
90 task
->timer
->Start(FROM_HERE
,
92 base::Bind(&DomainReliabilityDispatcher::MakeTaskEligible
,
93 base::Unretained(this),
98 DomainReliabilityDispatcher::MakeTaskEligible(Task
* 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),
110 void DomainReliabilityDispatcher::RunAndDeleteTask(Task
* task
) {
112 DCHECK(!task
->closure
.is_null());
115 eligible_tasks_
.erase(task
);
120 } // namespace domain_reliability