blob: a1d83ce59f24a766bd521a550affbe4e8a86d623 [file] [log] [blame]
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <algorithm>
#include "third_party/libjingle_xmpp/task_runner/taskrunner.h"
#include "base/logging.h"
#include "third_party/libjingle_xmpp/task_runner/task.h"
namespace jingle_xmpp {
TaskRunner::TaskRunner()
: TaskParent(this) {}
TaskRunner::~TaskRunner() {
// this kills and deletes children silently!
AbortAllChildren();
InternalRunTasks(true);
}
void TaskRunner::StartTask(Task * task) {
tasks_.push_back(task);
WakeTasks();
}
void TaskRunner::RunTasks() {
InternalRunTasks(false);
}
void TaskRunner::InternalRunTasks(bool in_destructor) {
// This shouldn't run while an abort is happening.
// If that occurs, then tasks may be deleted in this method,
// but pointers to them will still be in the
// "ChildSet copy" in TaskParent::AbortAllChildren.
// Subsequent use of those task may cause data corruption or crashes.
#if DCHECK_IS_ON
DCHECK(!abort_count_);
#endif
// Running continues until all tasks are Blocked (ok for a small # of tasks)
if (tasks_running_) {
return; // don't reenter
}
tasks_running_ = true;
int did_run = true;
while (did_run) {
did_run = false;
// use indexing instead of iterators because tasks_ may grow
for (size_t i = 0; i < tasks_.size(); ++i) {
while (!tasks_[i]->Blocked()) {
tasks_[i]->Step();
did_run = true;
}
}
}
// Tasks are deleted when running has paused
for (size_t i = 0; i < tasks_.size(); ++i) {
if (tasks_[i]->IsDone()) {
Task* task = tasks_[i];
#if DCHECK_IS_ON
deleting_task_ = task;
#endif
delete task;
#if DCHECK_IS_ON
deleting_task_ = NULL;
#endif
tasks_[i] = NULL;
}
}
// Finally, remove nulls
std::vector<Task *>::iterator it;
it = std::remove(tasks_.begin(), tasks_.end(), static_cast<Task*>(NULL));
tasks_.erase(it, tasks_.end());
tasks_running_ = false;
}
} // namespace jingle_xmpp