1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2006, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <algorithm> 29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/taskrunner.h" 31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/scoped_ptr.h" 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/task.h" 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochTaskRunner::TaskRunner() 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : TaskParent(this), 41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_(NULL), 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_running_(false) 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch , abort_count_(0), 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch deleting_task_(NULL) 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch{ 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochTaskRunner::~TaskRunner() { 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // this kills and deletes children silently! 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AbortAllChildren(); 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InternalRunTasks(true); 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::StartTask(Task * task) { 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_.push_back(task); 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // the task we just started could be about to timeout -- 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // make sure our "next timeout task" is correct 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UpdateTaskTimeout(task, 0); 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WakeTasks(); 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::RunTasks() { 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InternalRunTasks(false); 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::InternalRunTasks(bool in_destructor) { 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // This shouldn't run while an abort is happening. 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If that occurs, then tasks may be deleted in this method, 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // but pointers to them will still be in the 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // "ChildSet copy" in TaskParent::AbortAllChildren. 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Subsequent use of those task may cause data corruption or crashes. 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!abort_count_); 77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Running continues until all tasks are Blocked (ok for a small # of tasks) 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (tasks_running_) { 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; // don't reenter 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_running_ = true; 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 previous_timeout_time = next_task_timeout(); 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int did_run = true; 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (did_run) { 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch did_run = false; 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // use indexing instead of iterators because tasks_ may grow 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < tasks_.size(); ++i) { 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (!tasks_[i]->Blocked()) { 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_[i]->Step(); 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch did_run = true; 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Tasks are deleted when running has paused 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool need_timeout_recalc = false; 99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < tasks_.size(); ++i) { 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (tasks_[i]->IsDone()) { 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Task* task = tasks_[i]; 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (next_timeout_task_ && 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch task->unique_id() == next_timeout_task_->unique_id()) { 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_ = NULL; 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch need_timeout_recalc = true; 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch deleting_task_ = task; 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete task; 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef _DEBUG 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch deleting_task_ = NULL; 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_[i] = NULL; 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Finally, remove nulls 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::vector<Task *>::iterator it; 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch it = std::remove(tasks_.begin(), 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_.end(), 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch reinterpret_cast<Task *>(NULL)); 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_.erase(it, tasks_.end()); 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (need_timeout_recalc) 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RecalcNextTimeout(NULL); 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Make sure that adjustments are done to account 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // for any timeout changes (but don't call this 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // while being destroyed since it calls a pure virtual function). 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!in_destructor) 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CheckForTimeoutChange(previous_timeout_time); 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch tasks_running_ = false; 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::PollTasks() { 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // see if our "next potentially timed-out task" has indeed timed out. 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // If it has, wake it up, then queue up the next task in line 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Repeat while we have new timed-out tasks. 142731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: We need to guard against WakeTasks not updating 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // next_timeout_task_. Maybe also add documentation in the header file once 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // we understand this code better. 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Task* old_timeout_task = NULL; 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (next_timeout_task_ && 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch old_timeout_task != next_timeout_task_ && 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_->TimedOut()) { 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch old_timeout_task = next_timeout_task_; 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_->Wake(); 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WakeTasks(); 152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochint64 TaskRunner::next_task_timeout() const { 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (next_timeout_task_) { 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return next_timeout_task_->timeout_time(); 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return 0; 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// this function gets called frequently -- when each task changes 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// state to something other than DONE, ERROR or BLOCKED, it calls 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// ResetTimeout(), which will call this function to make sure that 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// the next timeout-able task hasn't changed. The logic in this function 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// prevents RecalcNextTimeout() from getting called in most cases, 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// effectively making the task scheduler O-1 instead of O-N 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::UpdateTaskTimeout(Task* task, 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 previous_task_timeout_time) { 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(task != NULL); 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 previous_timeout_time = next_task_timeout(); 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool task_is_timeout_task = next_timeout_task_ != NULL && 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch task->unique_id() == next_timeout_task_->unique_id(); 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (task_is_timeout_task) { 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch previous_timeout_time = previous_task_timeout_time; 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if the relevant task has a timeout, then 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // check to see if it's closer than the current 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // "about to timeout" task 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (task->timeout_time()) { 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (next_timeout_task_ == NULL || 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (task->timeout_time() <= next_timeout_task_->timeout_time())) { 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_ = task; 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (task_is_timeout_task) { 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // otherwise, if the task doesn't have a timeout, 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // and it used to be our "about to timeout" task, 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // walk through all the tasks looking for the real 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // "about to timeout" task 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch RecalcNextTimeout(task); 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Note when task_running_, then the running routine 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // (TaskRunner::InternalRunTasks) is responsible for calling 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // CheckForTimeoutChange. 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!tasks_running_) { 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CheckForTimeoutChange(previous_timeout_time); 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::RecalcNextTimeout(Task *exclude_task) { 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // walk through all the tasks looking for the one 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // which satisfies the following: 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // it's not finished already 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // we're not excluding it 208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // it has the closest timeout time 209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 next_timeout_time = 0; 211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_ = NULL; 212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch for (size_t i = 0; i < tasks_.size(); ++i) { 214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Task *task = tasks_[i]; 215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if the task isn't complete, and it actually has a timeout time 216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!task->IsDone() && (task->timeout_time() > 0)) 217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if it doesn't match our "exclude" task 218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (exclude_task == NULL || 219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch exclude_task->unique_id() != task->unique_id()) 220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if its timeout time is sooner than our current timeout time 221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (next_timeout_time == 0 || 222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch task->timeout_time() <= next_timeout_time) { 223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // set this task as our next-to-timeout 224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_time = task->timeout_time(); 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout_task_ = task; 226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid TaskRunner::CheckForTimeoutChange(int64 previous_timeout_time) { 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int64 next_timeout = next_task_timeout(); 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool timeout_change = (previous_timeout_time == 0 && next_timeout != 0) || 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch next_timeout < previous_timeout_time || 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch (previous_timeout_time <= CurrentTime() && 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch previous_timeout_time != next_timeout); 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (timeout_change) { 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch OnTimeoutChange(); 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base 242