OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "chrome/browser/policy/logging_work_scheduler.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/message_loop.h" | |
11 #include "content/public/browser/browser_thread.h" | |
12 | |
13 using content::BrowserThread; | |
14 | |
15 namespace policy { | |
16 | |
17 // Objects of this class are used in the priority-queue of future tasks | |
18 // in EventLogger. | |
19 class EventLogger::Task { | |
20 public: | |
21 Task(); | |
22 Task(int64 trigger_time, | |
23 int64 secondary_key, | |
24 linked_ptr<base::Closure> callback); | |
25 ~Task(); | |
26 | |
27 // Returns true if |this| should be executed before |rhs|. | |
28 // Used for sorting by the priority queue. | |
29 bool operator< (const Task& rhs) const; | |
30 | |
31 int64 trigger_time() const; | |
32 | |
33 // Returns a copy of the callback object of this task, and resets the | |
34 // original callback object. (LoggingTaskScheduler owns a linked_ptr to | |
35 // its task's callback objects and it only allows firing new tasks if the | |
36 // previous task's callback object has been reset.) | |
37 base::Closure GetAndResetCallback(); | |
38 | |
39 private: | |
40 // The virtual time when this task will trigger. | |
41 // Smaller times win. | |
42 int64 trigger_time_; | |
43 // Used for sorting tasks that have the same trigger_time. | |
44 // Bigger keys win. | |
45 int64 secondary_key_; | |
46 | |
47 linked_ptr<base::Closure> callback_; | |
48 }; | |
49 | |
50 EventLogger::Task::Task() { | |
51 } | |
52 | |
53 EventLogger::Task::Task(int64 trigger_time, | |
54 int64 secondary_key, | |
55 linked_ptr<base::Closure> callback) | |
56 : trigger_time_(trigger_time), | |
57 secondary_key_(secondary_key), | |
58 callback_(callback) { | |
59 } | |
60 | |
61 EventLogger::Task::~Task() { | |
62 } | |
63 | |
64 bool EventLogger::Task::operator< (const Task& rhs) const { | |
65 if (trigger_time_ == rhs.trigger_time_) { | |
66 return secondary_key_ < rhs.secondary_key_; | |
67 } else { | |
68 return trigger_time_ > rhs.trigger_time_; | |
69 } | |
70 } | |
71 | |
72 int64 EventLogger::Task::trigger_time() const { | |
73 return trigger_time_; | |
74 } | |
75 | |
76 base::Closure EventLogger::Task::GetAndResetCallback() { | |
77 // Make a copy. | |
78 base::Closure callback = *(callback_.get()); | |
79 // Reset the original callback, which is shared with LoggingTaskScheduler. | |
80 callback_->Reset(); | |
81 return callback; | |
82 } | |
83 | |
84 EventLogger::EventLogger() | |
85 : step_pending_(false), | |
86 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
87 current_time_(0), | |
88 task_counter_(0) { | |
89 } | |
90 | |
91 EventLogger::~EventLogger() { | |
92 } | |
93 | |
94 void EventLogger::PostDelayedWork( | |
95 linked_ptr<base::Closure> callback, | |
96 int64 delay) { | |
97 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
98 int64 trigger_time = current_time_ + delay; | |
99 task_counter_++; | |
100 scheduled_tasks_.push(Task(trigger_time, task_counter_, callback)); | |
101 if (!step_pending_) { | |
102 step_pending_ = true; | |
103 MessageLoop::current()->PostTask( | |
104 FROM_HERE, | |
105 base::Bind(&EventLogger::Step, weak_ptr_factory_.GetWeakPtr())); | |
106 } | |
107 } | |
108 | |
109 void EventLogger::RegisterEvent() { | |
110 events_.push_back(current_time_); | |
111 } | |
112 | |
113 void EventLogger::Swap(std::vector<int64>* events) { | |
114 std::swap(events_, *events); | |
115 } | |
116 | |
117 // static | |
118 // Counts the number of elements in a sorted integer vector that are | |
119 // >= |start| but < |start| + |length|. | |
120 int EventLogger::CountEvents(const std::vector<int64>& events, | |
121 int64 start, int64 length) { | |
122 // The first interesting event. | |
123 std::vector<int64>::const_iterator begin_it = | |
124 std::lower_bound(events.begin(), events.end(), start); | |
125 // The event after the last interesting event. | |
126 std::vector<int64>::const_iterator end_it = | |
127 std::lower_bound(begin_it, events.end(), start + length); | |
128 return end_it - begin_it; | |
129 } | |
130 | |
131 void EventLogger::Step() { | |
132 DCHECK(step_pending_); | |
133 step_pending_ = false; | |
134 if (scheduled_tasks_.empty()) | |
135 return; | |
136 // Take the next scheduled task from the queue. | |
137 Task next = scheduled_tasks_.top(); | |
138 scheduled_tasks_.pop(); | |
139 base::Closure callback = next.GetAndResetCallback(); | |
140 int64 trigger_time = next.trigger_time(); | |
141 DCHECK(trigger_time >= current_time_); | |
142 // Execute the next scheduled task if it was not cancelled. | |
143 if (!callback.is_null()) { | |
144 current_time_ = trigger_time; | |
145 callback.Run(); // Note: new items may be added to scheduled_tasks_ here. | |
146 } | |
147 // Trigger calling this method if there are remaining tasks. | |
148 if (!step_pending_ && !scheduled_tasks_.empty()) { | |
149 step_pending_ = true; | |
150 MessageLoop::current()->PostTask( | |
151 FROM_HERE, | |
152 base::Bind(&EventLogger::Step, weak_ptr_factory_.GetWeakPtr())); | |
153 } | |
154 } | |
155 | |
156 DummyWorkScheduler::DummyWorkScheduler() { | |
157 } | |
158 | |
159 DummyWorkScheduler::~DummyWorkScheduler() { | |
160 CancelDelayedWork(); | |
161 } | |
162 | |
163 void DummyWorkScheduler::PostDelayedWork( | |
164 const base::Closure& callback, int64 delay) { | |
165 DelayedWorkScheduler::PostDelayedWork(callback, 0); | |
166 } | |
167 | |
168 LoggingWorkScheduler::LoggingWorkScheduler(EventLogger* logger) | |
169 : logger_(logger) { | |
170 } | |
171 | |
172 LoggingWorkScheduler::~LoggingWorkScheduler() { | |
173 if (callback_.get()) | |
174 callback_->Reset(); | |
175 } | |
176 | |
177 void LoggingWorkScheduler::PostDelayedWork( | |
178 const base::Closure& callback, int64 delay) { | |
179 DCHECK(!callback_.get() || callback_->is_null()); | |
180 callback_.reset(new base::Closure(callback)); | |
181 logger_->PostDelayedWork(callback_, delay); | |
182 } | |
183 | |
184 void LoggingWorkScheduler::CancelDelayedWork() { | |
185 if (!callback_.get()) return; | |
186 callback_->Reset(); // Erase the callback to the delayed work. | |
187 callback_.reset(NULL); // Erase the pointer to the callback. | |
188 } | |
189 | |
190 } // namespace policy | |
OLD | NEW |