mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-02-24 19:56:00 +00:00
Improve search performance.
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
package org.signal.core.util.concurrent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A serial executor that will order pending tasks by a specified priority, and will only keep a single task of a given priority, preferring the latest.
|
||||
*
|
||||
* So imagine a world where the following tasks were all enqueued (meaning they're all waiting to be executed):
|
||||
*
|
||||
* execute(0, runnableA);
|
||||
* execute(3, runnableC1);
|
||||
* execute(3, runnableC2);
|
||||
* execute(2, runnableB);
|
||||
*
|
||||
* You'd expect the execution order to be:
|
||||
* - runnableC2
|
||||
* - runnableB
|
||||
* - runnableA
|
||||
*
|
||||
* (We order by priority, and C1 was replaced by C2)
|
||||
*/
|
||||
public final class LatestPrioritizedSerialExecutor {
|
||||
private final Queue<PriorityRunnable> tasks;
|
||||
private final Executor executor;
|
||||
private Runnable active;
|
||||
|
||||
public LatestPrioritizedSerialExecutor(@NonNull Executor executor) {
|
||||
this.executor = executor;
|
||||
this.tasks = new PriorityQueue<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute with a priority. Higher priorities are executed first.
|
||||
*/
|
||||
public synchronized void execute(int priority, @NonNull Runnable r) {
|
||||
Iterator<PriorityRunnable> iterator = tasks.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
if (iterator.next().getPriority() == priority) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
tasks.offer(new PriorityRunnable(priority) {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
r.run();
|
||||
} finally {
|
||||
scheduleNext();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (active == null) {
|
||||
scheduleNext();
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void scheduleNext() {
|
||||
if ((active = tasks.poll()) != null) {
|
||||
executor.execute(active);
|
||||
}
|
||||
}
|
||||
|
||||
private abstract static class PriorityRunnable implements Runnable, Comparable<PriorityRunnable> {
|
||||
private final int priority;
|
||||
|
||||
public PriorityRunnable(int priority) {
|
||||
this.priority = priority;
|
||||
}
|
||||
|
||||
public int getPriority() {
|
||||
return priority;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int compareTo(PriorityRunnable other) {
|
||||
return other.getPriority() - this.getPriority();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user