blob: ce159ffe43b684398393a207260eeff1a0e9c4bb [file] [log] [blame]
// Copyright 2018 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.base.task;
import org.chromium.base.TraceEvent;
import java.util.ArrayDeque;
/**
* Common implementation of a pre-native task runner which runs on either a thread pool or
* on a Handler, which can migrate posted tasks to native APIs.
*/
abstract class PreNativeSequence implements Runnable {
protected final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
private final String mTraceCategory;
private boolean mTaskRunning;
private boolean mMigrateToNative;
/**
* @param traceCategory The trace category to use when emitting trace events for tasks posted
* on this sequence.
*/
PreNativeSequence(String traceCategory) {
mTraceCategory = traceCategory;
}
/**
* @param task The task to be enqueued and run sequentially.
*/
synchronized void postTask(Runnable task) {
boolean wasEmpty = mTasks.isEmpty();
mTasks.offer(task);
if (wasEmpty && !mTaskRunning) scheduleNext();
}
/**
* Ensures the next task from this sequence is run via native APIs.
*/
synchronized void requestMigrateToNative() {
if (mTaskRunning) {
mMigrateToNative = true;
} else {
migrateToNative();
}
}
@Override
public void run() {
try (TraceEvent te = TraceEvent.scoped(mTraceCategory)) {
Runnable activeTask;
synchronized (this) {
if (mMigrateToNative) {
migrateToNative();
return;
}
activeTask = mTasks.poll();
mTaskRunning = true;
}
// Avoid holding the lock for too long, to allow other threads to postTask.
if (activeTask != null) activeTask.run();
synchronized (this) {
mTaskRunning = false;
if (!mTasks.isEmpty()) scheduleNext();
}
}
}
protected abstract void scheduleNext();
protected abstract void migrateToNative();
}