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" ); } }
}