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}