--- /dev/null
+// Copyright 2007 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.ibex.util;
+
+import java.io.*;
+
+// FEATURE: auto-rescheduling
+// (currently cronjobs must manually reschedule themselves)
+
+/**
+ * A manager for periodic tasks ("cron jobs")
+ */
+public final class Cron extends ImmortalThread {
+
+ private static ThreadPool threadPool;
+
+ private Vec tasks = new Vec();
+ private long wakeup = 0;
+
+ public Cron(ThreadPool threadPool) {
+ super(0);
+ this.threadPool = threadPool;
+ start();
+ }
+
+ public synchronized void cycle() {
+ try {
+ long now = System.currentTimeMillis();
+ if (wakeup == 0) wait();
+ else if (wakeup > now) wait(wakeup - now);
+ } catch (Exception e) { Log.error(this, e); }
+ wakeup = 0;
+ long now = System.currentTimeMillis();
+ // FIXME: linear scan is inefficient
+ for(int i=0; i<tasks.size(); i++) {
+ Task t = (Task)tasks.get(i);
+ if (t.when <= now) {
+ tasks.remove(i--);
+ threadPool.start(t.runnable);
+ } else {
+ if (wakeup == 0 || wakeup > t.when)
+ wakeup = t.when;
+ }
+ }
+ }
+
+ public void executeLater(long howLongFromNow, Runnable runnable) {
+ new Task(runnable, System.currentTimeMillis()+howLongFromNow);
+ }
+
+ private class Task {
+ final Runnable runnable;
+ final long when;
+ public Task(Runnable runnable, long when) {
+ this.runnable = runnable;
+ this.when = when;
+ synchronized(Cron.this) {
+ tasks.add(this);
+ if (wakeup == 0 || wakeup > when) {
+ wakeup = this.when;
+ Cron.this.notify();
+ }
+ }
+ }
+ }
+}
+