root/components/domain_reliability/dispatcher.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ScheduleTask
  2. RunEligibleTasks
  3. eligible
  4. MakeTaskWaiting
  5. MakeTaskEligible
  6. RunAndDeleteTask

// Copyright 2014 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.

#include "components/domain_reliability/dispatcher.h"

#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/stl_util.h"
#include "base/timer/timer.h"
#include "components/domain_reliability/util.h"

namespace domain_reliability {

DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
    : time_(time) {}

DomainReliabilityDispatcher::~DomainReliabilityDispatcher() {
  // TODO(ttuttle): STLElementDeleter?
  STLDeleteElements(&tasks_);
}

void DomainReliabilityDispatcher::ScheduleTask(
    const base::Closure& closure,
    base::TimeDelta min_delay,
    base::TimeDelta max_delay) {
  DCHECK(!closure.is_null());
  // Would be DCHECK_LE, but you can't << a TimeDelta.
  DCHECK(min_delay <= max_delay);

  Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay);
  tasks_.insert(task);
  if (max_delay.InMicroseconds() < 0)
    RunAndDeleteTask(task);
  else if (min_delay.InMicroseconds() < 0)
    MakeTaskEligible(task);
  else
    MakeTaskWaiting(task);
}

void DomainReliabilityDispatcher::RunEligibleTasks() {
  // Move all eligible tasks to a separate set so that eligible_tasks_.erase in
  // RunAndDeleteTask won't erase elements out from under the iterator.  (Also
  // keeps RunEligibleTasks from running forever if a task adds a new, already-
  // eligible task that does the same, and so on.)
  std::set<Task*> tasks;
  tasks.swap(eligible_tasks_);

  for (std::set<Task*>::const_iterator it = tasks.begin();
       it != tasks.end();
       ++it) {
    Task* task = *it;
    DCHECK(task);
    DCHECK(task->eligible);
    RunAndDeleteTask(task);
  }
}

DomainReliabilityDispatcher::Task::Task(const base::Closure& closure,
                                        scoped_ptr<MockableTime::Timer> timer,
                                        base::TimeDelta min_delay,
                                        base::TimeDelta max_delay)
    : closure(closure),
      timer(timer.Pass()),
      min_delay(min_delay),
      max_delay(max_delay),
      eligible(false) {}

DomainReliabilityDispatcher::Task::~Task() {}

void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
  DCHECK(task);
  DCHECK(!task->eligible);
  DCHECK(!task->timer->IsRunning());
  task->timer->Start(
      FROM_HERE,
      task->min_delay,
      base::Bind(
          &DomainReliabilityDispatcher::MakeTaskEligible,
          base::Unretained(this),
          task));
}

void
DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
  DCHECK(task);
  DCHECK(!task->eligible);
  task->eligible = true;
  eligible_tasks_.insert(task);
  task->timer->Start(
      FROM_HERE,
      task->max_delay - task->min_delay,
      base::Bind(
          &DomainReliabilityDispatcher::RunAndDeleteTask,
          base::Unretained(this),
          task));
}

void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
  DCHECK(task);
  DCHECK(!task->closure.is_null());
  task->closure.Run();
  if (task->eligible)
    eligible_tasks_.erase(task);
  tasks_.erase(task);
  delete task;
}

}  // namespace domain_reliability

/* [<][>][^][v][top][bottom][index][help] */