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

zmq.util.Timers Maven / Gradle / Ivy

The newest version!
package zmq.util;

import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;

import zmq.ZMQ;
import zmq.util.function.Supplier;

/**
 * Manages set of timers.
 * 

* Timers can be added with a given interval, when the interval of time expires after addition, handler method is executed with given arguments. * Timer is repetitive and will be executed over time until canceled. *

* This is a DRAFT class, and may change without notice. */ @Draft public final class Timers { public static final class Timer { private final Timers parent; private long interval; private boolean alive = true; private final Handler handler; private final Object[] args; private Timer(Timers parent, long interval, Handler handler, Object... args) { assert (args != null); this.parent = parent; this.interval = interval; this.handler = handler; this.args = args; } /** * Changes the interval of the timer. * This method is slow, canceling existing and adding a new timer yield better performance. * @param interval the new interval of the timer. * @return true if set, otherwise false. */ public boolean setInterval(long interval) { if (alive) { this.interval = interval; return parent.insert(this); } return false; } /** * Reset the timer. * This method is slow, canceling existing and adding a new timer yield better performance. * @return true if reset, otherwise false. */ public boolean reset() { if (alive) { return parent.insert(this); } return false; } /** * Cancels a timer. * @return true if cancelled, otherwise false. */ public boolean cancel() { if (alive) { alive = false; return true; } return false; } } public interface Handler { void time(Object... args); } private final MultiMap timers = new MultiMap<>(); private final Supplier clock; public Timers() { this(() -> TimeUnit.NANOSECONDS.toMillis(Clock.nowNS())); } /** * Builds a new timer. *

* This constructor is for testing and is not intended to be used in production code. * @param clock the supplier of the current time in milliseconds. */ public Timers(Supplier clock) { this.clock = clock; } private long now() { return clock.get(); } private boolean insert(Timer timer) { return timers.insert(now() + timer.interval, timer); } /** * Add timer to the set, timer repeats forever, or until cancel is called. * @param interval the interval of repetition in milliseconds. * @param handler the callback called at the expiration of the timer. * @param args the optional arguments for the handler. * @return an opaque handle for further cancel. */ public Timer add(long interval, Handler handler, Object... args) { if (handler == null) { return null; } Utils.checkArgument(interval > 0, "Delay of a timer has to be strictly greater than 0"); final Timer timer = new Timer(this, interval, handler, args); final boolean rc = insert(timer); assert (rc); return timer; } /** * Changes the interval of the timer. * This method is slow, canceling existing and adding a new timer yield better performance. * @param timer the timer to change the interval to. * @return true if set, otherwise false. * @deprecated use {@link Timer#setInterval(long)} instead */ @Deprecated public boolean setInterval(Timer timer, long interval) { assert (timer.parent == this); return timer.setInterval(interval); } /** * Reset the timer. * This method is slow, canceling existing and adding a new timer yield better performance. * @param timer the timer to reset. * @return true if reset, otherwise false. * @deprecated use {@link Timer#reset()} instead */ @Deprecated public boolean reset(Timer timer) { assert (timer.parent == this); return timer.reset(); } /** * Cancel a timer. * @param timer the timer to cancel. * @return true if cancelled, otherwise false. * @deprecated use {@link Timer#cancel()} instead */ @Deprecated public boolean cancel(Timer timer) { assert (timer.parent == this); return timer.cancel(); } /** * Returns the time in millisecond until the next timer. * @return the time in millisecond until the next timer. */ public long timeout() { final long now = now(); for (Entry entry : entries()) { final Timer timer = entry.getKey(); final Long expiration = entry.getValue(); if (timer.alive) { // Live timer, lets return the timeout if (expiration - now > 0) { return expiration - now; } else { return 0; } } // Remove it from the list of active timers. timers.remove(expiration, timer); } // Wait forever as no timers are alive return -1; } /** * Execute the timers. * @return the number of timers triggered. */ public int execute() { int executed = 0; final long now = now(); for (Entry entry : entries()) { final Timer timer = entry.getKey(); final Long expiration = entry.getValue(); // Dead timer, lets remove it and continue if (!timer.alive) { // Remove it from the list of active timers. timers.remove(expiration, timer); continue; } // Map is ordered, if we have to wait for current timer we can stop. if (expiration - now > 0) { break; } insert(timer); timer.handler.time(timer.args); ++executed; } return executed; } Iterable> entries() { return timers.entries(); } public int sleepAndExecute() { long timeout = timeout(); while (timeout > 0) { ZMQ.msleep(timeout); timeout = timeout(); } return execute(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy