add Cron
[org.ibex.util.git] / src / org / ibex / util / Cron.java
1 // Copyright 2007 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.util;
6
7 import java.io.*;
8
9 // FEATURE: auto-rescheduling
10 // (currently cronjobs must manually reschedule themselves)
11
12 /**
13  *  A manager for periodic tasks ("cron jobs")
14  */
15 public final class Cron extends ImmortalThread {
16
17     private static ThreadPool threadPool;
18
19     private Vec tasks = new Vec();
20     private long wakeup = 0;
21
22     public Cron(ThreadPool threadPool) {
23         super(0);
24         this.threadPool = threadPool;
25         start();
26     }
27
28     public synchronized void cycle() {
29         try {
30             long now = System.currentTimeMillis();
31             if (wakeup == 0)       wait();
32             else if (wakeup > now) wait(wakeup - now);
33         } catch (Exception e) { Log.error(this, e); }
34         wakeup = 0;
35         long now = System.currentTimeMillis();
36         // FIXME: linear scan is inefficient
37         for(int i=0; i<tasks.size(); i++) {
38             Task t = (Task)tasks.get(i);
39             if (t.when <= now) {
40                 tasks.remove(i--);
41                 threadPool.start(t.runnable);
42             } else {
43                 if (wakeup == 0 || wakeup > t.when)
44                     wakeup = t.when;
45             }
46         }
47     }
48
49     public void executeLater(long howLongFromNow, Runnable runnable) {
50         new Task(runnable, System.currentTimeMillis()+howLongFromNow);
51     }
52
53     private class Task {
54         final Runnable runnable;
55         final long     when;
56         public Task(Runnable runnable, long when) {
57             this.runnable = runnable;
58             this.when     = when;
59             synchronized(Cron.this) {
60                 tasks.add(this);
61                 if (wakeup == 0 || wakeup > when) {
62                     wakeup = this.when;
63                     Cron.this.notify();
64                 }
65             }
66         }
67     }
68 }
69