summaryrefslogtreecommitdiffstats
path: root/chrome/browser/policy/logging_work_scheduler.h
blob: c7bc587ff51771b05b563e1b40d3564cdd8418e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_
#define CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_
#pragma once

#include <queue>
#include <vector>

#include "base/basictypes.h"
#include "base/memory/linked_ptr.h"
#include "chrome/browser/policy/delayed_work_scheduler.h"

namespace policy {

// This implementation of DelayedWorkScheduler always schedules the tasks
// with zero delay.
class DummyWorkScheduler : public DelayedWorkScheduler {
 public:
  DummyWorkScheduler();
  virtual ~DummyWorkScheduler();

  virtual void PostDelayedWork(const base::Closure& callback, int64 delay);

 private:
  DISALLOW_COPY_AND_ASSIGN(DummyWorkScheduler);
};

// Helper class for LoggingWorkScheduler. It essentially emulates a real
// message loop. All the submitted tasks are run with zero delay, but the
// order in which they would run with delays is preserved.
// All the task posting requests of the schedulers will be channeled through
// a common instance of EventLogger. This makes sure, that this instance can
// keep track of time in the simulation and record logged events with correct
// timestamps.
class EventLogger {
 public:
  EventLogger();
  virtual ~EventLogger();

  // Post a task to be executed |delay| milliseconds from now. The task can be
  // cancelled later by calling Reset() on the callback.
  void PostDelayedWork(linked_ptr<base::Closure> callback, int64 delay);

 // Register a new event that happened now according to the internal clock.
  void RegisterEvent();

  // Swap out the internal list of events.
  void Swap(std::vector<int64>* events);

  // Counts the events in a sorted integer array that are >= |start| but
  // < |start| + |length|.
  static int CountEvents(const std::vector<int64>& events,
                         int64 start, int64 length);

 private:
  class Task {
   public:
    Task();
    Task(int64 trigger_time,
         int64 secondary_key,
         linked_ptr<base::Closure> callback);
    ~Task();

    // Returns true if |this| should be executed before |rhs|.
    // Used for sorting by the priority queue.
    bool operator< (const Task& rhs) const;

    int64 trigger_time() const;

    // Returns a copy of the callback object of this task, and resets the
    // original callback object. (LoggingTaskScheduler owns a linked_ptr to
    // its task's callback objects and it only allows firing new tasks if the
    // previous task's callback object has been reset.)
    base::Closure GetAndResetCallback();

   private:
    // The virtual time when this task will trigger.
    // Smaller times win.
    int64 trigger_time_;
    // Used for sorting tasks that have the same trigger_time.
    // Bigger keys win.
    int64 secondary_key_;

    linked_ptr<base::Closure> callback_;
  };

  // Updates |current_time_| and triggers the next scheduled task. This method
  // is run repeatedly on the main message loop until there are scheduled
  // tasks.
  void Step();

  // Stores the list of scheduled tasks with their respective delays and
  // schedulers.
  std::priority_queue<Task> scheduled_tasks_;

  // Machinery to put a call to |Step| at the end of the message loop.
  CancelableTask* step_task_;
  ScopedRunnableMethodFactory<EventLogger> method_factory_;

  // Ascending list of observation-times of the logged events.
  std::vector<int64> events_;
  // The current time of the simulated system.
  int64 current_time_;
  // The total number of tasks scheduled so far.
  int64 task_counter_;

  DISALLOW_COPY_AND_ASSIGN(EventLogger);
};

// Issues delayed tasks with zero effective delay, but posts them through
// an EventLogger, to make it possible to log events and reconstruct their
// execution time.
class LoggingWorkScheduler : public DelayedWorkScheduler {
 public:
  explicit LoggingWorkScheduler(EventLogger* logger);
  virtual ~LoggingWorkScheduler();

  virtual void PostDelayedWork(const base::Closure& callback, int64 delay);
  virtual void CancelDelayedWork();

 private:
  EventLogger* logger_;
  linked_ptr<base::Closure> callback_;

  DISALLOW_COPY_AND_ASSIGN(LoggingWorkScheduler);
};

}  // namespace policy

#endif  // CHROME_BROWSER_POLICY_LOGGING_WORK_SCHEDULER_H_