package com.bumptech.glide.load.engine.executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
/**
* A FIFO priority {@link ThreadPoolExecutor} that prioritizes submitted {@link Runnable}s by assuming they implement
* {@link Prioritized}. {@link Prioritized} runnables that return lower values for {@link Prioritized#getPriority()}
* will be executed before those that return higher values. Priorities only apply when multiple items are queued at the
* same time. Runnables with the same priority will be executed in FIFO order.
*/
public class FifoPriorityThreadPoolExecutor extends ThreadPoolExecutor {
AtomicInteger ordering = new AtomicInteger();
/**
* Constructor to build a fixed thread pool with the given pool size using {@link DefaultThreadFactory}.
* @param poolSize The number of threads.
*/
public FifoPriorityThreadPoolExecutor(int poolSize) {
this(poolSize, poolSize, 0, TimeUnit.MILLISECONDS, new DefaultThreadFactory());
}
public FifoPriorityThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit timeUnit,
ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAlive, timeUnit, new PriorityBlockingQueue<Runnable>(), threadFactory);
}
@Override
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FifoPriorityLoadTask<T>(runnable, value, ordering.getAndIncrement());
}
public static class DefaultThreadFactory implements ThreadFactory {
int threadNum = 0;
@Override
public Thread newThread(Runnable runnable) {
final Thread result = new Thread(runnable, "image-manager-resize-" + threadNum);
threadNum++;
result.setPriority(THREAD_PRIORITY_BACKGROUND);
return result;
}
}
private static class FifoPriorityLoadTask<T> extends FutureTask<T> implements Comparable<FifoPriorityLoadTask> {
private final int priority;
private final int order;
public FifoPriorityLoadTask(Runnable runnable, T result, int order) {
super(runnable, result);
if (!(runnable instanceof Prioritized)) {
throw new IllegalArgumentException("FifoPriorityThreadPoolExecutor must be given Runnables that " +
"implement Prioritized");
}
priority = ((Prioritized) runnable).getPriority();
this.order = order;
}
@Override
public int compareTo(FifoPriorityLoadTask loadTask) {
int result = priority - loadTask.priority;
if (result == 0 && loadTask != this) {
result = order - loadTask.order;
}
return result;
}
}
}