| Index: third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.cc
|
| diff --git a/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.cc b/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..3def8f730d84de8eb2fae7d8dd49fa5d46f388ef
|
| --- /dev/null
|
| +++ b/third_party/cacheinvalidation/src/google/cacheinvalidation/test/deterministic-scheduler.cc
|
| @@ -0,0 +1,84 @@
|
| +// 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.
|
| +
|
| +#include "google/cacheinvalidation/test/deterministic-scheduler.h"
|
| +
|
| +namespace invalidation {
|
| +
|
| +void DeterministicScheduler::StopScheduler() {
|
| + run_state_.Stop();
|
| + // Delete any tasks that haven't been run.
|
| + while (!work_queue_.empty()) {
|
| + TaskEntry top_elt = work_queue_.top();
|
| + work_queue_.pop();
|
| + delete top_elt.task;
|
| + }
|
| +}
|
| +
|
| +void DeterministicScheduler::Schedule(TimeDelta delay, Closure* task) {
|
| + CHECK(IsCallbackRepeatable(task));
|
| + CHECK(run_state_.IsStarted());
|
| + TLOG(logger_, INFO, "(Now: %d) Enqueuing %p with delay %d",
|
| + current_time_.ToInternalValue(), task, delay.InMilliseconds());
|
| + work_queue_.push(TaskEntry(GetCurrentTime() + delay, current_id_++, task));
|
| +}
|
| +
|
| +void DeterministicScheduler::PassTime(TimeDelta delta_time, TimeDelta step) {
|
| + CHECK(delta_time >= TimeDelta()) << "cannot pass a negative amount of time";
|
| + TimeDelta cumulative = TimeDelta();
|
| +
|
| + // Run tasks that are ready to run now.
|
| + RunReadyTasks();
|
| +
|
| + // Advance in increments of |step| until doing so would cause us to go past
|
| + // the requested |delta_time|.
|
| + while ((cumulative + step) < delta_time) {
|
| + ModifyTime(step);
|
| + cumulative += step;
|
| + RunReadyTasks();
|
| + }
|
| +
|
| + // Then advance one final time to finish out the interval.
|
| + ModifyTime(delta_time - cumulative);
|
| + RunReadyTasks();
|
| +}
|
| +
|
| +void DeterministicScheduler::RunReadyTasks() {
|
| + running_internal_ = true;
|
| + while (RunNextTask()) {
|
| + continue;
|
| + }
|
| + running_internal_ = false;
|
| +}
|
| +
|
| +bool DeterministicScheduler::RunNextTask() {
|
| + if (!work_queue_.empty()) {
|
| + // The queue is not empty, so get the first task and see if its scheduled
|
| + // execution time has passed.
|
| + TaskEntry top_elt = work_queue_.top();
|
| + if (top_elt.time <= GetCurrentTime()) {
|
| + // The task is scheduled to run in the past or present, so remove it
|
| + // from the queue and run the task.
|
| + work_queue_.pop();
|
| + TLOG(logger_, FINE, "(Now: %d) Running task %p",
|
| + current_time_.ToInternalValue(), top_elt.task);
|
| + top_elt.task->Run();
|
| + delete top_elt.task;
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| +} // namespace invalidation
|
|
|