Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / components / domain_reliability / dispatcher.cc
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
5 #include "components/domain_reliability/dispatcher.h"
6
7 #include "base/bind.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"
12
13 namespace domain_reliability {
14
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);
20   ~Task();
21
22   base::Closure closure;
23   scoped_ptr<MockableTime::Timer> timer;
24   base::TimeDelta min_delay;
25   base::TimeDelta max_delay;
26   bool eligible;
27 };
28
29 DomainReliabilityDispatcher::Task::Task(const base::Closure& closure,
30                                         scoped_ptr<MockableTime::Timer> timer,
31                                         base::TimeDelta min_delay,
32                                         base::TimeDelta max_delay)
33     : closure(closure),
34       timer(timer.Pass()),
35       min_delay(min_delay),
36       max_delay(max_delay),
37       eligible(false) {}
38
39 DomainReliabilityDispatcher::Task::~Task() {}
40
41 DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
42     : time_(time) {}
43
44 DomainReliabilityDispatcher::~DomainReliabilityDispatcher() {
45   // TODO(ttuttle): STLElementDeleter?
46   STLDeleteElements(&tasks_);
47 }
48
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);
56
57   Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay);
58   tasks_.insert(task);
59   if (max_delay.InMicroseconds() < 0)
60     RunAndDeleteTask(task);
61   else if (min_delay.InMicroseconds() < 0)
62     MakeTaskEligible(task);
63   else
64     MakeTaskWaiting(task);
65 }
66
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_);
74
75   for (std::set<Task*>::const_iterator it = tasks.begin();
76        it != tasks.end();
77        ++it) {
78     Task* task = *it;
79     DCHECK(task);
80     DCHECK(task->eligible);
81     RunAndDeleteTask(task);
82   }
83 }
84
85 void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
86   DCHECK(task);
87   DCHECK(!task->eligible);
88   DCHECK(!task->timer->IsRunning());
89   task->timer->Start(FROM_HERE,
90                      task->min_delay,
91                      base::Bind(&DomainReliabilityDispatcher::MakeTaskEligible,
92                                 base::Unretained(this),
93                                 task));
94 }
95
96 void
97 DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
98   DCHECK(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),
106                                 task));
107 }
108
109 void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
110   DCHECK(task);
111   DCHECK(!task->closure.is_null());
112   task->closure.Run();
113   if (task->eligible)
114     eligible_tasks_.erase(task);
115   tasks_.erase(task);
116   delete task;
117 }
118
119 }  // namespace domain_reliability