Commit 35fadcc6 authored by Karolina Soltys's avatar Karolina Soltys Committed by Commit Bot

[scheduler] Adding runOrPostTask to PostTask.

I am adding a function PostTask.runOrPostTask which executes
the task immediately if the current thread is the same as the
one corresponding to the SingleThreadTaskRunner, otherwise it
posts it. This function will be used to replace calls to
ThreadUtils.runOnUiThread.

Bug: 863341
Change-Id: Ie48d0c74f91e4189df3c70e1af805b2a38945cf3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1494882Reviewed-by: default avatarBo <boliu@chromium.org>
Reviewed-by: default avatarAndrew Grieve <agrieve@chromium.org>
Reviewed-by: default avatarAlex Clarke <alexclarke@chromium.org>
Commit-Queue: Karolina Soltys <ksolt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#638134}
parent 82aa1694
......@@ -52,4 +52,9 @@ class DefaultTaskExecutor implements TaskExecutor {
runner.postDelayedTask(task, delay);
}
}
@Override
public boolean canRunTaskImmediately(TaskTraits traits) {
return false;
}
}
......@@ -86,6 +86,27 @@ public class PostTask {
}
}
/**
* This function executes the task immediately if the current thread is the
* same as the one corresponding to the SingleThreadTaskRunner, otherwise it
* posts it.
*
* It should be executed only for tasks with traits corresponding to
* executors backed by a SingleThreadTaskRunner, like UiThreadTaskTraits.
*
* Use this only for trivial tasks as it ignores task priorities.
*
* @param taskTraits The TaskTraits that describe the desired TaskRunner.
* @param task The task to be run with the specified traits.
*/
public static void runOrPostTask(TaskTraits taskTraits, Runnable task) {
if (getTaskExecutorForTraits(taskTraits).canRunTaskImmediately(taskTraits)) {
task.run();
} else {
postTask(taskTraits, task);
}
}
/**
* Registers a TaskExecutor, this must be called before any other usages of this API.
*
......
......@@ -34,4 +34,10 @@ public interface TaskExecutor {
* @return The TaskRunner for the specified TaskTraits.
*/
public SingleThreadTaskRunner createSingleThreadTaskRunner(TaskTraits traits);
/**
* @return true iff the executor for these traits is backed by a SingleThreadTaskRunner
* associated with the current thread.
*/
public boolean canRunTaskImmediately(TaskTraits traits);
}
......@@ -16,6 +16,8 @@ import org.chromium.content.browser.UiThreadTaskTraitsImpl;
import java.util.WeakHashMap;
import javax.annotation.concurrent.GuardedBy;
/**
* This {@link TaskExecutor} is for tasks posted with {@link UiThreadTaskTraits}. It maps directly
* to content::BrowserTaskExecutor except only UI thread posting is supported from java.
......@@ -58,6 +60,11 @@ public class BrowserTaskExecutor implements TaskExecutor {
createSingleThreadTaskRunner(taskTraits).postDelayedTask(task, delay);
}
@Override
public boolean canRunTaskImmediately(TaskTraits traits) {
return createSingleThreadTaskRunner(traits).belongsToCurrentThread();
}
public static void register() {
// In some tests we will get called multiple times.
if (sRegistered) return;
......@@ -67,6 +74,7 @@ public class BrowserTaskExecutor implements TaskExecutor {
UiThreadTaskTraitsImpl.DESCRIPTOR.getId(), new BrowserTaskExecutor());
}
@GuardedBy("mTaskRunners")
private final WeakHashMap<TaskTraits, SingleThreadTaskRunner> mTaskRunners =
new WeakHashMap<>();
......
......@@ -140,6 +140,35 @@ public class UiThreadSchedulerTest {
}
}
@Test
@MediumTest
public void testRunOrPostTask() throws InterruptedException {
final Object lock = new Object();
final AtomicBoolean taskExecuted = new AtomicBoolean();
List<Integer> orderList = new ArrayList<>();
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
// We are running on the UI thread now. First, we post a task on the
// UI thread; it will not run immediately because the UI thread is
// busy running the current code:
PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
orderList.add(1);
synchronized (lock) {
taskExecuted.set(true);
lock.notify();
}
});
// Now, we runOrPost a task on the UI thread. We are on the UI thread,
// so it will run immediately.
PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { orderList.add(2); });
});
synchronized (lock) {
while (!taskExecuted.get()) {
lock.wait();
}
}
assertThat(orderList, contains(2, 1));
}
private void startContentMainOnUiThread() {
final Object lock = new Object();
final AtomicBoolean uiThreadInitalized = new AtomicBoolean();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment