[go: up one dir, main page]

blob: ee157a2c284ce9fd7f4156a2c0c0367ea46bdbf1 [file] [log] [blame]
// Copyright 2017 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.
package org.chromium.chrome.browser.init;
import android.util.Pair;
import org.chromium.base.ThreadUtils;
import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import java.util.LinkedList;
/**
* Allows to chain multiple tasks on the UI thread, with the next task posted when one completes.
*
* Threading:
* - Can construct and call {@link add()} on any thread. Note that this is not synchronized.
* - Can call {@link start()} on any thread, blocks if called from the UI thread and coalesceTasks
* is true.
* - {@link cancel()} must be called from the UI thread.
*/
public class ChainedTasks {
private LinkedList<Pair<TaskTraits, Runnable>> mTasks = new LinkedList<>();
private volatile boolean mFinalized;
private final Runnable mRunAndPost = new Runnable() {
@Override
public void run() {
if (mTasks.isEmpty()) return;
Pair<TaskTraits, Runnable> pair = mTasks.pop();
pair.second.run();
if (!mTasks.isEmpty()) PostTask.postTask(mTasks.peek().first, this);
}
};
/**
* Adds a task to the list of tasks to run. Cannot be called once {@link start()} has been
* called.
*/
public void add(TaskTraits traits, Runnable task) {
if (mFinalized) throw new IllegalStateException("Must not call add() after start()");
mTasks.add(new Pair<>(traits, task));
}
/**
* Cancels the remaining tasks. Must be called from the UI thread.
*/
public void cancel() {
if (!ThreadUtils.runningOnUiThread()) {
throw new IllegalStateException("Must call cancel() from the UI thread.");
}
mFinalized = true;
mTasks.clear();
}
/**
* Posts or runs all the tasks, one by one.
*
* @param coalesceTasks if false, posts the tasks. Otherwise run them in a single task. If
* called on the UI thread, run in the current task.
*/
public void start(final boolean coalesceTasks) {
if (mFinalized) throw new IllegalStateException("Cannot call start() several times");
mFinalized = true;
if (mTasks.isEmpty()) return;
if (coalesceTasks) {
PostTask.runOrPostTask(mTasks.peek().first, new Runnable() {
@Override
public void run() {
for (Pair<TaskTraits, Runnable> pair : mTasks) pair.second.run();
mTasks.clear();
}
});
} else {
PostTask.postTask(mTasks.peek().first, mRunAndPost);
}
}
}