| Index: third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.h
|
| diff --git a/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.h b/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..932932f9d7d3d6cbaa3e74df8b230028a535cdb7
|
| --- /dev/null
|
| +++ b/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.h
|
| @@ -0,0 +1,152 @@
|
| +// Copyright 2012 Google Inc.
|
| +//
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +// you may not use this file except in compliance with the License.
|
| +// You may obtain a copy of the License at
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +// distributed under the License is distributed on an "AS IS" BASIS,
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// See the License for the specific language governing permissions and
|
| +// limitations under the License.
|
| +
|
| +// An implementation of the Scheduler interface for unit testing (in a
|
| +// single-threaded environment).
|
| +
|
| +#ifndef GOOGLE_CACHEINVALIDATION_TEST_DETERMINISTIC_SCHEDULER_H_
|
| +#define GOOGLE_CACHEINVALIDATION_TEST_DETERMINISTIC_SCHEDULER_H_
|
| +
|
| +#include <queue>
|
| +#include <string>
|
| +#include <utility>
|
| +
|
| +#include "google/cacheinvalidation/include/system-resources.h"
|
| +#include "google/cacheinvalidation/deps/callback.h"
|
| +#include "google/cacheinvalidation/deps/logging.h"
|
| +#include "google/cacheinvalidation/deps/string_util.h"
|
| +#include "google/cacheinvalidation/deps/time.h"
|
| +#include "google/cacheinvalidation/impl/log-macro.h"
|
| +#include "google/cacheinvalidation/impl/run-state.h"
|
| +
|
| +namespace invalidation {
|
| +
|
| +// An entry in the work queue. Ensures that tasks don't run until their
|
| +// scheduled time, and for a given time, they run in the order in which they
|
| +// were enqueued.
|
| +struct TaskEntry {
|
| + TaskEntry(Time time, int64 id, Closure* task)
|
| + : time(time), id(id), task(task) {}
|
| +
|
| + bool operator<(const TaskEntry& other) const {
|
| + // Priority queue returns *largest* element first.
|
| + return (time > other.time) ||
|
| + ((time == other.time) && (id > other.id));
|
| + }
|
| + Time time; // the time at which to run
|
| + int64 id; // the order in which this task was enqueued
|
| + Closure* task; // the task to be run
|
| +};
|
| +
|
| +class DeterministicScheduler : public Scheduler {
|
| + public:
|
| + // Caller retains ownershup of |logger|.
|
| + explicit DeterministicScheduler(Logger* logger)
|
| + : current_id_(0), running_internal_(false), logger_(logger) {}
|
| +
|
| + virtual ~DeterministicScheduler() {
|
| + StopScheduler();
|
| + }
|
| +
|
| + virtual void SetSystemResources(SystemResources* resources) {
|
| + // Nothing to do.
|
| + }
|
| +
|
| + virtual Time GetCurrentTime() const {
|
| + return current_time_;
|
| + }
|
| +
|
| + void StartScheduler() {
|
| + run_state_.Start();
|
| + }
|
| +
|
| + void StopScheduler();
|
| +
|
| + virtual void Schedule(TimeDelta delay, Closure* task);
|
| +
|
| + virtual bool IsRunningOnThread() const {
|
| + return running_internal_;
|
| + }
|
| +
|
| + void SetInitialTime(Time new_time) {
|
| + current_time_ = new_time;
|
| + }
|
| +
|
| + // Passes |delta_time| in increments of at most |step|, executing all pending
|
| + // tasks during that interval.
|
| + void PassTime(TimeDelta delta_time, TimeDelta step);
|
| +
|
| + // Passes |delta_time| in default-sized increments, executing all pending
|
| + // tasks.
|
| + void PassTime(TimeDelta delta_time) {
|
| + PassTime(delta_time, DefaultTimeStep());
|
| + }
|
| +
|
| + private:
|
| + // Runs all the work in the queue that should be executed by the current time.
|
| + // Note that tasks run may enqueue additional immediate tasks, and this call
|
| + // won't return until they've completed as well. While these tasks are
|
| + // running, the running_internal_ flag is set, so IsRunningOnThread()
|
| + // will return true.
|
| + void RunReadyTasks();
|
| +
|
| + // Default time step when simulating passage of time. Chosen to be
|
| + // significantly smaller than any scheduling interval used by the client
|
| + // library.
|
| + static TimeDelta DefaultTimeStep() {
|
| + return TimeDelta::FromMilliseconds(10);
|
| + }
|
| +
|
| + void ModifyTime(TimeDelta delta_time) {
|
| + current_time_ += delta_time;
|
| + }
|
| +
|
| + // Attempts to run a task, returning true is there was a task to run.
|
| + bool RunNextTask();
|
| +
|
| + // The current time, which may be set by the test.
|
| + Time current_time_;
|
| +
|
| + // The id number of the next task.
|
| + uint64 current_id_;
|
| +
|
| + // Whether or not the scheduler has been started/stopped.
|
| + RunState run_state_;
|
| +
|
| + // Whether or not we're currently running internal tasks from the internal
|
| + // queue.
|
| + bool running_internal_;
|
| +
|
| + // A priority queue on which the actual tasks are enqueued.
|
| + std::priority_queue<TaskEntry> work_queue_;
|
| +
|
| + // A logger.
|
| + Logger* logger_;
|
| +};
|
| +
|
| +// A simple deterministic scheduler that always indicates that it is on
|
| +// the correct thread.
|
| +class SimpleDeterministicScheduler : public DeterministicScheduler {
|
| + public:
|
| + explicit SimpleDeterministicScheduler(Logger* logger)
|
| + : DeterministicScheduler(logger) {}
|
| +
|
| + virtual bool IsRunningOnThread() const {
|
| + return true;
|
| + }
|
| +};
|
| +
|
| +} // namespace invalidation
|
| +
|
| +#endif // GOOGLE_CACHEINVALIDATION_TEST_DETERMINISTIC_SCHEDULER_H_
|
|
|