About timers and their trigger times
In an event expression, when you specify the within, wait, or at operator you are specifying a timer. Every timer has a trigger time. The trigger time is when you want the timer to fire.
When you use the
within operator, the trigger time is when the specified length of time elapses. If a
within timer fires, the listener fails. In the following listener, the trigger time is 30 seconds after
A becomes true.
A -> B within(30.0)
If B becomes true within 30 seconds, the trigger time for the timer is not reached, the timer does not fire, the listener triggers, and the monitor calls any attached JMon listeners. If B does not become true within 30 seconds, the trigger time is reached, the timer fires, and the listener fails. The monitor does not call the MatchListener.
When you use the
wait operator, the trigger time is when the specified pause during processing of the event expression has elaspsed. When a
wait timer fires, processing continues. In the following expression, the trigger time is 20 seconds after
A becomes true. When the trigger time is reached, the timer fires. The listener then starts watching for
B. When
B is true, the monitor calls any attached listeners.
A -> wait(20.0) -> B
When you use the
at operator, the trigger time is one or more specific times. An
at timer fires at the specified times. In the following expression, the trigger time is five minutes past each hour every day. This timer fires 24 times each day. When the timer fires, the monitor calls any attached JMon listeners.
all at(5, *, *, *, *)
At each clock tick, the correlator evaluates each timer to determine whether that timer’s trigger time has been reached. If a timer’s trigger time has been reached, the correlator fires that timer. When a timer’s trigger time is exactly at the same time as a clock tick, the timer fires at its exact trigger time. When a timer’s trigger time is not exactly at the same time as a clock tick, the timer fires at the next clock tick. This means that if a timer’s trigger time is .01 seconds after a clock tick, that timer does not fire until .09 seconds later.
When a timer fires, the current time is always the trigger time of the timer. This is regardless of whether the timer fired at its trigger time or at the first clock tick after its trigger time.
A single clock tick can make a repeating timer fire multiple times. For example, if you specify all wait(0.01), this timer fires 10 times every tenth of a second.
Because of rounding constraints,
A timer such as
all wait(0.1) drifts away from firing every tenth of a second. The drift is of the order of milliseconds per century, but you can notice the drift if you convert the value of the current time to a string.
Two timers that you might expect to fire at the same instant might fire at different, though very close, times.
The rounding constraint is that you cannot accurately express 0.1 seconds as a float because you cannot represent it in binary notation. For example, the on wait(0.1) listener waits for 0.10000000000000000555 seconds.
To specify a timer that fires exactly 10 times per second, calculate the length of time to wait by using a method that does not accumulate rounding errors. For example, calculate a whole part and a fractional part:
@Application(author="Tim Berners", company="Apama",
description="Demonstrate tenth of second timers", name="Tenth",
version="1.0")
@MonitorType
public class TenthOfSecond implements Monitor {
private static final Logger LOGGER =
Logger.getLogger(TenthOfSecond.class);
private static final NumberFormat formatter =
NumberFormat.getInstance();
static { formatter.setGroupingUsed(false); }
double startTime;
double fraction;
public void onLoad() {
startTime = Math.ceil( Correlator.getCurrentTime() );
fraction = Math.ceil(
(Correlator.getCurrentTime() - startTime) * 10.0);
setupTimeListener();
}
void setupTimeListener() {
fraction++;
if (10.0 <= fraction) {
fraction = 0.0;
startTime++;
}
EventExpression ee = new EventExpression("wait("+ ((startTime +
(fraction / 10.0))-Correlator.getCurrentTime()) +")");
ee.addMatchListener(new MatchListener() {
public void match(MatchEvent evt) {
LOGGER.info(formatter.format(Correlator.getCurrentTime()));
// System.out.println(Correlator.getCurrentTime());
// This would go to STDOUT, and isn't as pretty
new TestEvent(Correlator.getCurrentTime()).emit();
setupTimeListener();
}
});
}
}
// TenthOfSecond
When a timer fires, the correlator processes items in the following order. The correlator
1. Triggers all listeners that trigger at the same time.
2. Routes any events, and routes any events that those events route, and so on.
3. Fires any timers at the next trigger time.