1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file. 4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/domain_reliability/dispatcher.h" 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/bind.h" 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "base/callback.h" 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/message_loop/message_loop.h" 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/stl_util.h" 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/timer/timer.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "components/domain_reliability/util.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace domain_reliability { 15effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 160de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)struct DomainReliabilityDispatcher::Task { 170de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) Task(const base::Closure& closure, 180de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) scoped_ptr<MockableTime::Timer> timer, 190de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta min_delay, 200de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta max_delay); 210de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) ~Task(); 220de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 230de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::Closure closure; 240de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) scoped_ptr<MockableTime::Timer> timer; 250de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta min_delay; 260de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta max_delay; 270de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) bool eligible; 280de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}; 290de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 300de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)DomainReliabilityDispatcher::Task::Task(const base::Closure& closure, 310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) scoped_ptr<MockableTime::Timer> timer, 320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta min_delay, 330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::TimeDelta max_delay) 340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) : closure(closure), 350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) timer(timer.Pass()), 360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) min_delay(min_delay), 370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) max_delay(max_delay), 380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) eligible(false) {} 390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)DomainReliabilityDispatcher::Task::~Task() {} 410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) 42effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time) 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : time_(time) {} 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 45effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDomainReliabilityDispatcher::~DomainReliabilityDispatcher() { 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // TODO(ttuttle): STLElementDeleter? 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch STLDeleteElements(&tasks_); 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DomainReliabilityDispatcher::ScheduleTask( 51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const base::Closure& closure, 52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta min_delay, 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::TimeDelta max_delay) { 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!closure.is_null()); 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Would be DCHECK_LE, but you can't << a TimeDelta. 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(min_delay <= max_delay); 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay); 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tasks_.insert(task); 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (max_delay.InMicroseconds() < 0) 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RunAndDeleteTask(task); 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch else if (min_delay.InMicroseconds() < 0) 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeTaskEligible(task); 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch else 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch MakeTaskWaiting(task); 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DomainReliabilityDispatcher::RunEligibleTasks() { 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Move all eligible tasks to a separate set so that eligible_tasks_.erase in 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // RunAndDeleteTask won't erase elements out from under the iterator. (Also 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // keeps RunEligibleTasks from running forever if a task adds a new, already- 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // eligible task that does the same, and so on.) 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::set<Task*> tasks; 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tasks.swap(eligible_tasks_); 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::set<Task*>::const_iterator it = tasks.begin(); 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != tasks.end(); 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Task* task = *it; 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(task); 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(task->eligible); 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch RunAndDeleteTask(task); 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) { 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(task); 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!task->eligible); 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!task->timer->IsRunning()); 900de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task->timer->Start(FROM_HERE, 910de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task->min_delay, 920de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::Bind(&DomainReliabilityDispatcher::MakeTaskEligible, 930de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::Unretained(this), 940de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task)); 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid 98effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochDomainReliabilityDispatcher::MakeTaskEligible(Task* task) { 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(task); 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!task->eligible); 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch task->eligible = true; 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch eligible_tasks_.insert(task); 1030de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task->timer->Start(FROM_HERE, 1040de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task->max_delay - task->min_delay, 1050de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::Bind(&DomainReliabilityDispatcher::RunAndDeleteTask, 1060de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) base::Unretained(this), 1070de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles) task)); 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) { 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(task); 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!task->closure.is_null()); 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch task->closure.Run(); 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (task->eligible) 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch eligible_tasks_.erase(task); 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch tasks_.erase(task); 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch delete task; 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace domain_reliability 121