/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
package com.espertech.esper.timer;
/**
* Allow for different strategies for getting VM (wall clock) time.
* See JIRA issue ESPER-191 Support nano/microsecond resolution for more
* information on Java system time-call performance, accuracy and drift.
* @author Jerry Shea
*/
public class TimeSourceServiceImpl implements TimeSourceService
{
private static final long MICROS_TO_MILLIS = 1000;
private static final long NANOS_TO_MICROS = 1000;
/**
* A public variable indicating whether to use the System millisecond time or
* nano time, to be configured through the engine settings.
*/
public static boolean IS_SYSTEM_CURRENT_TIME = true;
private final long wallClockOffset;
private final String description;
/**
* Ctor.
*/
public TimeSourceServiceImpl()
{
this.wallClockOffset = System.currentTimeMillis() * MICROS_TO_MILLIS - this.getTimeMicros();
this.description = String.format("%s: resolution %d microsecs",
this.getClass().getSimpleName(), this.calculateResolution());
}
/**
* Convenience method to get time in milliseconds
* @return wall-clock time in milliseconds
*/
public long getTimeMillis() {
if (IS_SYSTEM_CURRENT_TIME)
{
return System.currentTimeMillis();
}
return getTimeMicros() / MICROS_TO_MILLIS;
}
private long getTimeMicros() {
return (System.nanoTime() / NANOS_TO_MICROS) + wallClockOffset;
}
/**
* Calculate resolution of this timer in microseconds i.e. what is the resolution
* of the underlying platform's timer.
* @return timer resolution
*/
protected long calculateResolution() {
final int LOOPS = 5;
long totalResolution = 0;
long time = this.getTimeMicros(), prevTime = time;
for (int i = 0; i < LOOPS; i++) {
// wait until time changes
while (time == prevTime)
time = this.getTimeMicros();
totalResolution += (time - prevTime);
prevTime = time;
}
return totalResolution / LOOPS;
}
@Override
public String toString() {
return description;
}
}