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