SerialSingleThreadExecutor.java

 1package eu.siacs.conversations.utils;
 2
 3import android.util.Log;
 4
 5import java.util.ArrayDeque;
 6import java.util.concurrent.Executor;
 7import java.util.concurrent.Executors;
 8
 9import eu.siacs.conversations.Config;
10
11public class SerialSingleThreadExecutor implements Executor {
12
13    final ArrayDeque<Runnable> tasks = new ArrayDeque<>();
14    private final Executor executor = Executors.newSingleThreadExecutor();
15    private final String name;
16    protected Runnable active;
17
18
19    public SerialSingleThreadExecutor(String name) {
20        this.name = name;
21    }
22
23    public synchronized void execute(final Runnable r) {
24        tasks.offer(new Runner(r));
25        if (active == null) {
26            scheduleNext();
27        }
28    }
29
30    private synchronized void scheduleNext() {
31        if ((active = tasks.poll()) != null) {
32            executor.execute(active);
33            int remaining = tasks.size();
34            if (remaining > 0) {
35                Log.d(Config.LOGTAG, remaining + " remaining tasks on executor '" + name + "'");
36            }
37        }
38    }
39
40    private class Runner implements Runnable, Cancellable {
41
42        private final Runnable runnable;
43
44        private Runner(Runnable runnable) {
45            this.runnable = runnable;
46        }
47
48        @Override
49        public void cancel() {
50            if (runnable instanceof Cancellable) {
51                ((Cancellable) runnable).cancel();
52            }
53        }
54
55        @Override
56        public void run() {
57            try {
58                runnable.run();
59            } finally {
60                scheduleNext();
61            }
62        }
63    }
64}