All Downloads are FREE. Search and download functionalities are using the official Maven repository.

nz.sodium.time.TimerSystem Maven / Gradle / Ivy

There is a newer version: 1.2.0
Show newest version
package nz.sodium.time;

import nz.sodium.*;
import java.util.LinkedList;
import java.util.Optional;

public class TimerSystem {
    public TimerSystem(final TimerSystemImpl impl) {
        this.impl = impl;
        final CellSink timeSnk = new CellSink(impl.now());
        time = timeSnk;
        Transaction.onStart(new Runnable() {
            public void run() {
                T t = impl.now();
                impl.runTimersTo(t);
                while (true) {
                    Event ev;
                    // Pop all events earlier than t.
                    synchronized (eventQueue) {
                        ev = eventQueue.peekFirst();
                        if (ev != null && ev.t.compareTo(t) <= 0)
                            eventQueue.removeFirst();
                        else
                            ev = null;
                    }
                    if (ev != null) {
                        timeSnk.send(ev.t);
                        ev.sAlarm.send(ev.t);
                    }
                    else
                        break;
                }
                timeSnk.send(t);
            }
        });
    }

    private final TimerSystemImpl impl;
    /**
     * A cell giving the current clock time.
     */
    public final Cell time;

    private class Event {
        Event(T t, StreamSink sAlarm) {
            this.t = t;
            this.sAlarm = sAlarm;
        }
        T t;
        StreamSink sAlarm;
    };
    private LinkedList eventQueue = new LinkedList();

    private static class CurrentTimer {
        Optional oTimer = Optional.empty();
    };

    /**
     * A timer that fires at the specified time.
     */
    public Stream at(Cell> tAlarm) {
        final StreamSink sAlarm = new StreamSink();
        final CurrentTimer current = new CurrentTimer();
        Listener l = tAlarm.listen(new Handler>() {
            public void run(final Optional oAlarm) {
                if (current.oTimer.isPresent())
                    current.oTimer.get().cancel();
                current.oTimer = oAlarm.isPresent()
                    ? Optional.of(
                        impl.setTimer(oAlarm.get(), new Runnable() {
                            public void run() {
                                synchronized (eventQueue) {
                                    eventQueue.add(new Event(oAlarm.get(), sAlarm));
                                }
                                // Open and close a transaction to trigger queued
                                // events to run.
                                Transaction.runVoid(new Runnable() {
                                    public void run() { }
                                });
                            }
                        }))
                    : Optional.empty();
            }
        });
        return sAlarm.addCleanup(l);
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy