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