blob: 46b1b102f8f015220860e8d3c71842bf877c1542 [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 org.chromium.base.annotations.JNINamespace;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
/**
* Implementation of the abstract class {@link TaskRunnerImpl}. Uses AsyncTasks until
* native APIs are available.
*/
@JNINamespace("base")
public class TaskRunnerImpl implements TaskRunner {
@Nullable
private final TaskTraits mTaskTraits;
private final Object mLock = new Object();
private long mNativeTaskRunnerAndroid;
@Nullable
private List<PreNativeTask> mPreNativeTasks = new ArrayList<>();
/**
* @param traits The TaskTraits associated with this TaskRunnerImpl.
*/
TaskRunnerImpl(TaskTraits traits) {
mTaskTraits = traits;
}
@Override
protected void finalize() {
if (mNativeTaskRunnerAndroid != 0) nativeFinalize(mNativeTaskRunnerAndroid);
}
@Override
public void postTask(Runnable task) {
synchronized (mLock) {
if (mNativeTaskRunnerAndroid != 0) {
nativePostTask(mNativeTaskRunnerAndroid, task);
return;
}
// We don't expect a whole lot of these, if that changes consider pooling them.
PreNativeTask preNativeTask = new PreNativeTask(task);
mPreNativeTasks.add(preNativeTask);
AsyncTask.THREAD_POOL_EXECUTOR.execute(preNativeTask);
}
}
private class PreNativeTask implements Runnable {
PreNativeTask(Runnable task) {
this.mTask = task;
}
@Override
public void run() {
try (TraceEvent te = TraceEvent.scoped("TaskRunnerImpl.PreNativeTask.run")) {
synchronized (mLock) {
if (mPreNativeTasks == null) return;
mPreNativeTasks.remove(this);
}
mTask.run();
}
}
final Runnable mTask;
}
@Override
public void initNativeTaskRunner() {
synchronized (mLock) {
mNativeTaskRunnerAndroid = nativeInit(mTaskTraits.mPrioritySetExplicitly,
mTaskTraits.mPriority, mTaskTraits.mMayBlock, mTaskTraits.mExtensionId,
mTaskTraits.mExtensionData);
for (PreNativeTask task : mPreNativeTasks) {
nativePostTask(mNativeTaskRunnerAndroid, task.mTask);
}
mPreNativeTasks = null;
}
}
// NB due to Proguard obfuscation it's easiest to pass the traits via arguments.
private static native long nativeInit(boolean prioritySetExplicitly, int priority,
boolean mayBlock, byte extensionId, byte[] extensionData);
private native void nativeFinalize(long nativeTaskRunnerAndroid);
private native void nativePostTask(long nativeTaskRunnerAndroid, Runnable task);
}