blob: efc15db0c2b0ddee3b2a5ddffc9920797caba2d9 [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.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;
/**
* Java interface to the native chromium scheduler. Note tasks can be posted before native
* initialization, but task prioritization is extremely limited. Once the native scheduler
* is ready, tasks will be migrated over.
*/
@JNINamespace("base")
public class PostTask {
private static final Object sLock = new Object();
private static Set<TaskRunner> sPreNativeTaskRunners =
Collections.newSetFromMap(new WeakHashMap<TaskRunner, Boolean>());
private static final TaskExecutor sTaskExecutors[] = getInitialTaskExecutors();
private static TaskExecutor[] getInitialTaskExecutors() {
TaskExecutor taskExecutors[] = new TaskExecutor[TaskTraits.MAX_EXTENSION_ID + 1];
taskExecutors[0] = new DefaultTaskExecutor();
return taskExecutors;
}
/**
* @param traits The TaskTraits that describe the desired TaskRunner.
* @return The TaskRunner for the specified TaskTraits.
*/
public static TaskRunner createTaskRunner(TaskTraits taskTraits) {
synchronized (sLock) {
return getTaskExecutorForTraits(taskTraits).createTaskRunner(taskTraits);
}
}
/**
* @param traits The TaskTraits that describe the desired TaskRunner.
* @return The TaskRunner for the specified TaskTraits.
*/
public static SequencedTaskRunner createSequencedTaskRunner(TaskTraits taskTraits) {
synchronized (sLock) {
return getTaskExecutorForTraits(taskTraits).createSequencedTaskRunner(taskTraits);
}
}
/**
*
* @param traits The TaskTraits that describe the desired TaskRunner.
* @return The TaskRunner for the specified TaskTraits.
*/
public static SingleThreadTaskRunner createSingleThreadTaskRunner(TaskTraits taskTraits) {
synchronized (sLock) {
return getTaskExecutorForTraits(taskTraits).createSingleThreadTaskRunner(taskTraits);
}
}
/**
* @param taskTraits The TaskTraits that describe the desired TaskRunner.
* @param task The task to be run with the specified traits.
*/
public static void postTask(TaskTraits taskTraits, Runnable task) {
postDelayedTask(taskTraits, task, 0);
}
/**
* @param taskTraits The TaskTraits that describe the desired TaskRunner.
* @param task The task to be run with the specified traits.
* @param delay The delay in milliseconds before the task can be run.
*/
public static void postDelayedTask(TaskTraits taskTraits, Runnable task, long delay) {
synchronized (sLock) {
if (sPreNativeTaskRunners != null) {
getTaskExecutorForTraits(taskTraits).postDelayedTask(taskTraits, task, delay);
} else {
nativePostDelayedTask(taskTraits.mPrioritySetExplicitly, taskTraits.mPriority,
taskTraits.mMayBlock, taskTraits.mExtensionId, taskTraits.mExtensionData,
task, delay);
}
}
}
/**
* Registers a TaskExecutor, this must be called before any other usages of this API.
*
* @param extensionId The id associated with the TaskExecutor.
* @param taskExecutor The TaskExecutor to be registered. Must not equal zero.
*/
public static void registerTaskExecutor(int extensionId, TaskExecutor taskExecutor) {
synchronized (sLock) {
assert extensionId != 0;
assert extensionId <= TaskTraits.MAX_EXTENSION_ID;
assert sTaskExecutors[extensionId] == null;
sTaskExecutors[extensionId] = taskExecutor;
}
}
/**
* Called by every TaskRunner on its creation, attempts to register this
* TaskRunner as pre-native, unless the native scheduler has been
* initialised already, and informs the caller about the outcome. Called
* only when sLock has already been acquired.
*
* @param taskRunner The TaskRunner to be registered.
* @return If the taskRunner got registered as pre-native.
*/
static boolean registerPreNativeTaskRunnerLocked(TaskRunner taskRunner) {
if (sPreNativeTaskRunners != null) {
sPreNativeTaskRunners.add(taskRunner);
return true;
}
return false;
}
private static TaskExecutor getTaskExecutorForTraits(TaskTraits traits) {
return sTaskExecutors[traits.mExtensionId];
}
@CalledByNative
private static void onNativeTaskSchedulerReady() {
synchronized (sLock) {
for (TaskRunner taskRunner : sPreNativeTaskRunners) {
taskRunner.initNativeTaskRunner();
}
sPreNativeTaskRunners = null;
}
}
// This is here to make C++ tests work.
@CalledByNative
private static void onNativeTaskSchedulerShutdown() {
synchronized (sLock) {
sPreNativeTaskRunners =
Collections.newSetFromMap(new WeakHashMap<TaskRunner, Boolean>());
}
}
private static native void nativePostDelayedTask(boolean prioritySetExplicitly, int priority,
boolean mayBlock, byte extensionId, byte[] extensionData, Runnable task, long delay);
}