| 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 |