Scheduler.java revision e2c2daa717063899e30b0cafd4d81e60a36d6b0f
1package com.xtremelabs.robolectric.util;
2
3import java.util.ArrayList;
4import java.util.Collections;
5import java.util.List;
6import java.util.ListIterator;
7
8public class Scheduler {
9    private List<PostedRunnable> postedRunnables = new ArrayList<PostedRunnable>();
10    private long currentTime = 0;
11    private boolean paused = false;
12
13
14    public void pause() {
15        paused = true;
16    }
17
18    public void unPause() {
19        paused = false;
20        advanceToLastPostedRunnable();
21    }
22
23    public boolean isPaused() {
24        return paused;
25    }
26
27    public void postDelayed(Runnable runnable, long delayMillis) {
28        if (paused || delayMillis > 0) {
29            postedRunnables.add(new PostedRunnable(runnable, currentTime + delayMillis));
30            Collections.sort(postedRunnables);
31        } else {
32            runnable.run();
33        }
34    }
35
36    public void post(Runnable runnable) {
37        postDelayed(runnable, 0);
38    }
39
40    public void remove(Runnable runnable) {
41        ListIterator<PostedRunnable> iterator = postedRunnables.listIterator();
42        while (iterator.hasNext()) {
43            PostedRunnable next = iterator.next();
44            if (next.runnable == runnable) {
45                iterator.remove();
46            }
47        }
48    }
49
50    public boolean advanceToLastPostedRunnable() {
51        if (enqueuedTaskCount() < 1) {
52            return false;
53        }
54
55        return advanceTo(postedRunnables.get(postedRunnables.size() - 1).scheduledTime);
56    }
57
58    public boolean advanceToNextPostedRunnable() {
59        if (enqueuedTaskCount() < 1) {
60            return false;
61        }
62
63        return advanceTo(postedRunnables.get(0).scheduledTime);
64    }
65
66    public boolean advanceBy(long intervalMs) {
67        long endingTime = currentTime + intervalMs;
68        return advanceTo(endingTime);
69    }
70
71    public boolean advanceTo(long endingTime) {
72        if (endingTime - currentTime < 0 || enqueuedTaskCount() < 1) {
73            return false;
74        }
75
76        int runCount = 0;
77        while (nextTaskIsScheduledBefore(endingTime)) {
78            runOneTask();
79            ++runCount;
80        }
81        currentTime = endingTime;
82
83        return runCount > 0;
84    }
85
86    public boolean runOneTask() {
87        if (enqueuedTaskCount() < 1) {
88            return false;
89        }
90
91        PostedRunnable postedRunnable = postedRunnables.remove(0);
92        currentTime = postedRunnable.scheduledTime;
93        postedRunnable.run();
94        return true;
95    }
96
97    public boolean runTasks(int howMany) {
98        if (enqueuedTaskCount() < howMany) {
99            return false;
100        }
101
102        while (howMany > 0) {
103            PostedRunnable postedRunnable = postedRunnables.remove(0);
104            currentTime = postedRunnable.scheduledTime;
105            postedRunnable.run();
106            howMany--;
107        }
108        return true;
109    }
110
111    public int enqueuedTaskCount() {
112        return postedRunnables.size();
113    }
114
115    public boolean areAnyRunnable() {
116        return nextTaskIsScheduledBefore(currentTime);
117    }
118
119    public void reset() {
120        postedRunnables.clear();
121        paused = false;
122    }
123
124    class PostedRunnable implements Comparable<PostedRunnable> {
125        Runnable runnable;
126        long scheduledTime;
127
128        PostedRunnable(Runnable runnable, long scheduledTime) {
129            this.runnable = runnable;
130            this.scheduledTime = scheduledTime;
131        }
132
133        @Override
134        public int compareTo(PostedRunnable postedRunnable) {
135            return (int) (scheduledTime - postedRunnable.scheduledTime);
136        }
137
138        public void run() {
139            runnable.run();
140        }
141    }
142
143    private boolean nextTaskIsScheduledBefore(long endingTime) {
144        return enqueuedTaskCount() > 0 && postedRunnables.get(0).scheduledTime <= endingTime;
145    }
146}
147