package hitimes;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.Ruby; import org.jruby.RubyClass; import org.jruby.RubyObject;
import org.jruby.runtime.Block; import org.jruby.runtime.ObjectAllocator; import org.jruby.runtime.ThreadContext;
import org.jruby.anno.JRubyClass; import org.jruby.anno.JRubyMethod;
@JRubyClass( name = “Hitimes::Interval” ) public class HitimesInterval extends RubyObject {
this is a double to force all division by the conversion factor
to cast to doubles
private static final double INSTANT_CONVERSION_FACTOR = 1000000000d;
private static final long INSTANT_NOT_SET = Long.MIN_VALUE;
private static final double DURATION_NOT_SET = Double.NaN;
public static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new HitimesInterval( runtime, klass );
}
};
public HitimesInterval( Ruby runtime, RubyClass klass ) {
super( runtime, klass );
}
public HitimesInterval( Ruby runtime, RubyClass klass, long start ) {
super( runtime, klass );
this.start_instant = start;
}
private long start_instant = INSTANT_NOT_SET;
private long stop_instant = INSTANT_NOT_SET;
private double duration = DURATION_NOT_SET;
@JRubyMethod( name = "duration", alias = { "length", "to_f", "to_seconds" } )
public IRubyObject duration() {
/*
if start has not yet been called, then raise an exception.
/
if ( INSTANT_NOT_SET == this.start_instant ) {
throw Hitimes.newHitimesError( getRuntime(), "Attempt to report a duration on an interval that has not started");
}
/*
if stop has not yet been called, then return the amount of time so far
/
if ( INSTANT_NOT_SET == this.stop_instant ) {
double d = ( System.nanoTime() - this.start_instant ) / INSTANT_CONVERSION_FACTOR;
return getRuntime().newFloat( d );
}
/*
if stop has been called, then calculate the duration and return
/
if ( DURATION_NOT_SET == this.duration ) {
this.duration = (this.stop_instant - this.start_instant) / INSTANT_CONVERSION_FACTOR;
}
return getRuntime().newFloat( this.duration );
}
@JRubyMethod( name = "duration_so_far" )
public IRubyObject duration_so_far() {
IRubyObject rc = getRuntime().getFalse();
if ( INSTANT_NOT_SET == this.start_instant ) {
return rc;
}
if ( INSTANT_NOT_SET == this.stop_instant ) {
double d = ( System.nanoTime() - this.start_instant ) / INSTANT_CONVERSION_FACTOR;
return getRuntime().newFloat( d );
}
return rc;
}
@JRubyMethod( name = "started?" )
public IRubyObject is_started() {
if ( INSTANT_NOT_SET == this.start_instant ) {
return getRuntime().getFalse();
}
return getRuntime().getTrue();
}
@JRubyMethod( name = "running?" )
public IRubyObject is_running() {
if ( ( INSTANT_NOT_SET != this.start_instant ) && ( INSTANT_NOT_SET == this.stop_instant ) ) {
return getRuntime().getTrue();
}
return getRuntime().getFalse();
}
@JRubyMethod( name = "stopped?" )
public IRubyObject is_stopped() {
if ( INSTANT_NOT_SET == this.stop_instant ) {
return getRuntime().getFalse();
}
return getRuntime().getTrue();
}
@JRubyMethod( name = "start_instant" )
public IRubyObject start_instant() {
return getRuntime().newFixnum( this.start_instant );
}
@JRubyMethod( name = "stop_instant" )
public IRubyObject stop_instant() {
return getRuntime().newFixnum( this.stop_instant );
}
@JRubyMethod( name = "start" )
public IRubyObject start() {
if ( INSTANT_NOT_SET == this.start_instant ) {
this.start_instant = System.nanoTime();
return getRuntime().getTrue();
}
return getRuntime().getFalse();
}
@JRubyMethod( name = "stop" )
public IRubyObject stop() {
if ( INSTANT_NOT_SET == this.start_instant ) {
throw Hitimes.newHitimesError( getRuntime(), "Attempt to stop an interval that has not started" );
}
if ( INSTANT_NOT_SET == this.stop_instant ) {
this.stop_instant = System.nanoTime();
this.duration = (this.stop_instant - this.start_instant) / INSTANT_CONVERSION_FACTOR;
return getRuntime().newFloat( this.duration );
}
return getRuntime().getFalse();
}
@JRubyMethod( name = "split" )
public IRubyObject split() {
this.stop();
return new HitimesInterval( getRuntime(), Hitimes.hitimesIntervalClass, this.stop_instant );
}
@JRubyMethod( name = "now", module = true )
public static IRubyObject now( IRubyObject self ) {
return new HitimesInterval( self.getRuntime(), Hitimes.hitimesIntervalClass, System.nanoTime() );
}
@JRubyMethod( name = "measure", module = true, frame = true )
public static IRubyObject measure( IRubyObject self, Block block ) {
Ruby runtime = self.getRuntime();
if ( block.isGiven() ) {
IRubyObject nil = runtime.getNil();
ThreadContext context = runtime.getCurrentContext();
HitimesInterval interval = new HitimesInterval( runtime, Hitimes.hitimesIntervalClass );
interval.start();
block.yield( context, nil );
interval.stop();
return interval.duration();
} else {
throw Hitimes.newHitimesError( runtime, "No block given to Interval.measure" );
}
}
}