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