hitimes 0.3.0-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/HISTORY ADDED
@@ -0,0 +1,21 @@
1
+ = Changelog
2
+
3
+ == Version 0.3.0
4
+
5
+ * switched to extconf for building extensions
6
+ * first release of windows binary gem
7
+ * reverted back to normal rdoc
8
+
9
+ == Version 0.2.1
10
+
11
+ * added Timer#rate method
12
+ * switched to darkfish rdoc
13
+
14
+ == Version 0.2.0
15
+
16
+ * Performance improvements
17
+ * Added Stats class
18
+
19
+ == Version 0.1.0
20
+
21
+ * Initial completion
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008 Jeremy Hinegardner
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README ADDED
@@ -0,0 +1,79 @@
1
+ == hitimes
2
+
3
+ * Homepage[http://copiousfreetime.rubyforge.org/hitimes]
4
+ * {Rubyforge project}[http://rubyforge.org/projects/copiousfreetime/]
5
+ * email jeremy at copiousfreetime dot org
6
+ * git clone url git://github.com/copiousfreetime/hitimes.git
7
+
8
+ == INSTALL
9
+
10
+ * gem install hitimes
11
+
12
+ == DESCRIPTION
13
+
14
+ Hitimes is a fast, high resolution timer library for recording performance
15
+ metrics. It uses the appropriate C method calls for each system to get the
16
+ highest granularity time increments possible.
17
+
18
+ It currently supports any system with the POSIX call clock_gettime() and OSX.
19
+ Windows is in the works.
20
+
21
+ Using Hitimes can be faster than using a series of Time.new calls, and it will
22
+ have a much higher granularity. It is definitely faster than using
23
+ Process.times.
24
+
25
+ == SYNOPSIS
26
+
27
+ Use Hitimes::Interval to calculate only the duration of a block of code
28
+
29
+ duration = Hitimes::Interval.measure do
30
+ # some operation ...
31
+ end
32
+
33
+ puts duration
34
+
35
+ Use a Hitimes::Timer to calculate statistics about an iterative operation
36
+
37
+ timer = Hitimes::Timer.new
38
+ collection.each do |item|
39
+ timer.start
40
+ # .. do something with item
41
+ timer.stop
42
+ end
43
+
44
+ puts timer.mean
45
+ puts timer.median
46
+ puts timer.max
47
+ puts timer.min
48
+ puts timer.stddev
49
+
50
+
51
+ == CHANGES
52
+
53
+ Read the HISTORY file.
54
+
55
+ == CREDITS
56
+
57
+ * Bruce Williams for suggesting the idea
58
+
59
+ == MIT LICENSE
60
+
61
+ Copyright (c) 2008 Jeremy Hinegardner
62
+
63
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
64
+ this software and associated documentation files (the "Software"), to deal in
65
+ the Software without restriction, including without limitation the rights to
66
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
67
+ of the Software, and to permit persons to whom the Software is furnished to do
68
+ so, subject to the following conditions:
69
+
70
+ The above copyright notice and this permission notice shall be included in all
71
+ copies or substantial portions of the Software.
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
76
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
77
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
78
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79
+ SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,63 @@
1
+ #--
2
+ # Copyright (c) 2008 Jeremy Hinegardner
3
+ # All rights reserved. See LICENSE and/or COPYING for details.
4
+ #++
5
+
6
+ #-------------------------------------------------------------------------------
7
+ # make sure our project's top level directory and the lib directory are added to
8
+ # the ruby search path.
9
+ #-------------------------------------------------------------------------------
10
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"ext"))
11
+ $: << File.expand_path(File.join(File.dirname(__FILE__),"lib"))
12
+ $: << File.expand_path(File.dirname(__FILE__))
13
+
14
+
15
+ #-------------------------------------------------------------------------------
16
+ # load the global project configuration and add in the top level clean and
17
+ # clobber tasks so that other tasks can utilize those constants if necessary
18
+ # This loads up the defaults for the whole project configuration
19
+ #-------------------------------------------------------------------------------
20
+ require 'rubygems'
21
+ require 'tasks/config.rb'
22
+ require 'rake/clean'
23
+
24
+ #-------------------------------------------------------------------------------
25
+ # Main configuration for the project, these overwrite the items that are in
26
+ # tasks/config.rb
27
+ #-------------------------------------------------------------------------------
28
+ require 'hitimes/version'
29
+ require 'hitimes/paths'
30
+
31
+ Configuration.for("project") {
32
+ name "hitimes"
33
+ version Hitimes::VERSION
34
+ author "Jeremy Hinegardner"
35
+ email "jeremy@copiousfreetime.org"
36
+ homepage "http://copiousfreetime.rubyforge.org/hitimes/"
37
+ }
38
+
39
+ #-------------------------------------------------------------------------------
40
+ # load up all the project tasks and setup the default task to be the
41
+ # test:default task.
42
+ #-------------------------------------------------------------------------------
43
+ Configuration.for("packaging").files.tasks.each do |tasklib|
44
+ import tasklib
45
+ end
46
+ task :default => 'test:default'
47
+
48
+ #-------------------------------------------------------------------------------
49
+ # Finalize the loading of all pending imports and update the top level clobber
50
+ # task to depend on all possible sub-level tasks that have a name like
51
+ # ':clobber' in other namespaces. This allows us to say:
52
+ #
53
+ # rake clobber
54
+ #
55
+ # and it will get everything.
56
+ #-------------------------------------------------------------------------------
57
+ Rake.application.load_imports
58
+ Rake.application.tasks.each do |t|
59
+ if t.name =~ /:clobber/ then
60
+ task :clobber => [t.name]
61
+ end
62
+ end
63
+
@@ -0,0 +1,86 @@
1
+ require 'benchmark'
2
+ require 'time'
3
+
4
+ #
5
+ # this is all here in case this example is run from the examples directory
6
+ #
7
+ begin
8
+ require 'hitimes'
9
+ rescue LoadError => le
10
+ ext_path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "ext" ) )
11
+ lib_path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", "lib" ) )
12
+ if $:.include?( ext_path ) then
13
+ raise le
14
+ end
15
+ $: << ext_path
16
+ $: << lib_path
17
+ retry
18
+ end
19
+
20
+ #----------------------------------------------------------------------
21
+ # test program to look at the performance sampling time durations using
22
+ # different methods
23
+ #----------------------------------------------------------------------
24
+
25
+ include Benchmark
26
+
27
+ #
28
+ # Normal apprach to Interval usage
29
+ #
30
+ def hitimes_duration_i1
31
+ i = Hitimes::Interval.new
32
+ i.start
33
+ i.stop
34
+ end
35
+
36
+ #
37
+ # Use the easy access method to start stop an interval
38
+ #
39
+ def hitimes_duration_i2
40
+ Hitimes::Interval.now.stop
41
+ end
42
+
43
+ #
44
+ # Use a new timer each time
45
+ #
46
+ def hitimes_duration_t1
47
+ Hitimes::Timer.now.stop
48
+ end
49
+
50
+ #
51
+ # reuse the same timer over and over
52
+ #
53
+ HT = Hitimes::Timer.new
54
+ def hitimes_duration_t2
55
+ HT.start
56
+ HT.stop
57
+ end
58
+
59
+ #
60
+ # use the Struct::Tms values and return the difference in User time between 2
61
+ # successive calls
62
+ #
63
+ def process_duration
64
+ t1 = Process.times.utime
65
+ Process.times.utime - t1
66
+ end
67
+
68
+ #
69
+ # Take 2 times and subtract one from the other
70
+ #
71
+ def time_duration
72
+ t1 = Time.now.to_f
73
+ Time.now.to_f - t1
74
+ end
75
+
76
+
77
+ puts "Testing time sampling 100,000 times"
78
+
79
+ bm(20) do |x|
80
+ x.report("Process") { 100_000.times { process_duration } }
81
+ x.report("Time") { 100_000.times { time_duration } }
82
+ x.report("Hitimes::Timer 1") { 100_000.times { hitimes_duration_t1 } }
83
+ x.report("Hitimes::Timer 2") { 100_000.times { hitimes_duration_t2 } }
84
+ x.report("Hitimes::Interval 1") { 100_000.times { hitimes_duration_i1 } }
85
+ x.report("Hitimes::Interval 2") { 100_000.times { hitimes_duration_i2 } }
86
+ end
data/examples/stats.rb ADDED
@@ -0,0 +1,29 @@
1
+ #
2
+ # this is all here in case this example is run from the examples directory
3
+ #
4
+ begin
5
+ require 'hitimes'
6
+ rescue LoadError => le
7
+ %w[ ext lib ].each do |p|
8
+ path = File.expand_path( File.join( File.dirname( __FILE__ ), "..", p ) )
9
+ if $:.include?( path ) then
10
+ raise le
11
+ end
12
+ $: << path
13
+ end
14
+ retry
15
+ end
16
+
17
+ s = Hitimes::Stats.new
18
+ dir = ARGV.shift || Dir.pwd
19
+ Dir.entries( dir ).each do |entry|
20
+ fs = File.stat( entry )
21
+ if fs.file? then
22
+ s.update( fs.size )
23
+ end
24
+ end
25
+
26
+ %w[ count min max mean sum stddev ].each do |m|
27
+ puts "#{m.rjust(6)} : #{s.send( m ) }"
28
+ end
29
+
data/ext/extconf.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'rbconfig'
2
+ require 'mkmf'
3
+
4
+ if Config::CONFIG['host_os'] =~ /darwin/ then
5
+ $CFLAGS += " -DUSE_INSTANT_OSX=1"
6
+ $LDFLAGS += " -framework CoreServices"
7
+ elsif Config::CONFIG['host_os'] =~ /win32/ or Config::CONFIG['host_os'] =~ /mingw/ then
8
+ $CFLAGS += " -DUSE_INSTANT_WINDOWS=1"
9
+ else
10
+ if have_library("rt", "clock_gettime") then
11
+ $CFLAGS += " -DUSE_INSTANT_CLOCK_GETTIME=1"
12
+ end
13
+ end
14
+
15
+ create_makefile('hitimes_ext')
data/ext/hitimes_ext.c ADDED
@@ -0,0 +1,20 @@
1
+ #include <ruby.h>
2
+
3
+ /* Module and Classes */
4
+ VALUE mH; /* module Hitimes */
5
+ VALUE eH_Error; /* class Hitimes::Error */
6
+
7
+ /*
8
+ * Document-class: Hitimes::Error
9
+ *
10
+ * General error class for the Hitimes module
11
+ */
12
+ void Init_hitimes_ext( )
13
+ {
14
+ mH = rb_define_module("Hitimes");
15
+
16
+ eH_Error = rb_define_class_under(mH, "Error", rb_eStandardError);
17
+
18
+ Init_hitimes_interval();
19
+ Init_hitimes_stats( );
20
+ }
@@ -0,0 +1,20 @@
1
+ #ifdef USE_INSTANT_CLOCK_GETTIME
2
+
3
+ #include "hitimes_interval.h"
4
+
5
+ #include <sys/time.h>
6
+
7
+ hitimes_instant_t hitimes_get_current_instant( )
8
+ {
9
+ struct timespec time;
10
+ int rc;
11
+
12
+ rc = clock_gettime( CLOCK_MONOTONIC, &time);
13
+ if ( 0 != rc ) {
14
+ char* e = strerror( rc );
15
+ rb_raise(eH_Error, "Unable to retrieve time for CLOCK_MONOTONIC : %s", e );
16
+ }
17
+
18
+ return ( ( NANOSECONDS_PER_SECOND * (long)time.tv_sec ) + time.tv_nsec );
19
+ }
20
+ #endif
@@ -0,0 +1,16 @@
1
+ #ifdef USE_INSTANT_OSX
2
+
3
+ #include "hitimes_interval.h"
4
+ #include <CoreServices/CoreServices.h>
5
+
6
+ /*
7
+ * returns the number of nanoseconds since the machine was booted
8
+ */
9
+ hitimes_instant_t hitimes_get_current_instant( )
10
+ {
11
+ Nanoseconds nano = AbsoluteToNanoseconds( UpTime() );
12
+
13
+ return *( hitimes_instant_t *)&nano;
14
+ }
15
+
16
+ #endif
@@ -0,0 +1,27 @@
1
+ #ifdef USE_INSTANT_WINDOWS
2
+
3
+ #include "hitimes_interval.h"
4
+
5
+
6
+ /*
7
+ * returns the conversion factor, this value is used to convert
8
+ * the value from hitimes_get_current_instant() into seconds
9
+ */
10
+ double hitimes_instant_conversion_factor()
11
+ {
12
+ LARGE_INTEGER ticks_per_second;
13
+ QueryPerformanceFrequency( &ticks_per_second );
14
+ return (double)ticks_per_second.QuadPart;
15
+ }
16
+
17
+ /*
18
+ * returns the number of ticks
19
+ */
20
+ hitimes_instant_t hitimes_get_current_instant()
21
+ {
22
+ LARGE_INTEGER tick;
23
+ QueryPerformanceCounter(&tick);
24
+ return (hitimes_instant_t)tick.QuadPart;
25
+ }
26
+
27
+ #endif
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Copyright (c) 2008 Jeremy Hinegardner
3
+ * All rights reserved. See LICENSE and/or COPYING for details.
4
+ *
5
+ * vim: shiftwidth=4
6
+ */
7
+
8
+ #include "hitimes_interval.h"
9
+
10
+ /* Modules and Classes -- defined here */
11
+ VALUE cH_Interval; /* class Hitimes::Interval */
12
+
13
+ /**
14
+ * Allocator and Deallocator for Interval classes
15
+ */
16
+
17
+ VALUE hitimes_interval_free(hitimes_interval_t* i)
18
+ {
19
+ if ( Qnil != i->duration ) {
20
+ rb_gc_unregister_address( &(i->duration) );
21
+ i->duration = Qnil;
22
+ }
23
+ xfree( i );
24
+ return Qnil;
25
+ }
26
+
27
+ VALUE hitimes_interval_alloc(VALUE klass)
28
+ {
29
+ VALUE obj;
30
+ hitimes_interval_t* i = xmalloc( sizeof( hitimes_interval_t ) );
31
+
32
+ i->start_instant = 0L;
33
+ i->stop_instant = 0L;
34
+ i->duration = Qnil;
35
+
36
+ obj = Data_Wrap_Struct(klass, NULL, hitimes_interval_free, i);
37
+ return obj;
38
+ }
39
+
40
+ /**
41
+ * call-seq:
42
+ * Interval.now -> Interval
43
+ *
44
+ * Create an interval that has already started
45
+ */
46
+ VALUE hitimes_interval_now( VALUE self )
47
+ {
48
+ VALUE obj;
49
+ hitimes_interval_t *i = xmalloc( sizeof( hitimes_interval_t ) );
50
+
51
+ i->start_instant = hitimes_get_current_instant( );
52
+ i->stop_instant = 0L;
53
+ i->duration = Qnil;
54
+
55
+ obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, i);
56
+
57
+ return obj;
58
+ }
59
+
60
+ /**
61
+ * call-seq:
62
+ * Interval.measure { } -> Float
63
+ *
64
+ * Times the execution of the block returning the number of seconds it took
65
+ */
66
+ VALUE hitimes_interval_measure( VALUE self )
67
+ {
68
+ hitimes_instant_t before;
69
+ hitimes_instant_t after;
70
+ double duration;
71
+
72
+ if ( !rb_block_given_p() ) {
73
+ rb_raise(eH_Error, "No block given to Interval.measure" );
74
+ }
75
+
76
+ before = hitimes_get_current_instant( );
77
+ rb_yield( Qnil );
78
+ after = hitimes_get_current_instant( );
79
+
80
+ duration = ( after - before ) / HITIMES_INSTANT_CONVERSION_FACTOR;
81
+ return rb_float_new( duration );
82
+ }
83
+
84
+ /**
85
+ * call-seq:
86
+ * interval.split -> Interval
87
+ *
88
+ * Immediately stop the current interval and start a new interval that has a
89
+ * start_instant equivalent to the stop_interval of self.
90
+ */
91
+ VALUE hitimes_interval_split( VALUE self )
92
+ {
93
+ hitimes_interval_t *first;
94
+ hitimes_interval_t *second = xmalloc( sizeof( hitimes_interval_t ) );
95
+ VALUE obj;
96
+
97
+ Data_Get_Struct( self, hitimes_interval_t, first );
98
+ first->stop_instant = hitimes_get_current_instant( );
99
+
100
+ second->start_instant = first->stop_instant;
101
+ second->stop_instant = 0L;
102
+ second->duration = Qnil;
103
+
104
+ obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, second);
105
+
106
+ return obj;
107
+ }
108
+
109
+
110
+ /**
111
+ * call-seq:
112
+ * interval.start -> boolean
113
+ *
114
+ * mark the start of the interval. Calling start on an already started
115
+ * interval has no effect. An interval can only be started once. If the
116
+ * interval is truely started +true+ is returned otherwise +false+.
117
+ */
118
+ VALUE hitimes_interval_start( VALUE self )
119
+ {
120
+ hitimes_interval_t *i;
121
+ VALUE rc = Qfalse;
122
+
123
+ Data_Get_Struct( self, hitimes_interval_t, i );
124
+ if ( 0L == i->start_instant ) {
125
+ i->start_instant = hitimes_get_current_instant( );
126
+ i->stop_instant = 0L;
127
+ i->duration = Qnil;
128
+
129
+ rc = Qtrue;
130
+ }
131
+
132
+ return rc;
133
+ }
134
+
135
+
136
+ /**
137
+ * call-seq:
138
+ * interval.stop -> bool or Float
139
+ *
140
+ * mark the stop of the interval. Calling stop on an already stopped interval
141
+ * has no effect. An interval can only be stopped once. If the interval is
142
+ * truely stopped then the duration is returned, otherwise +false+.
143
+ */
144
+ VALUE hitimes_interval_stop( VALUE self )
145
+ {
146
+ hitimes_interval_t *i;
147
+ VALUE rc = Qfalse;
148
+
149
+ Data_Get_Struct( self, hitimes_interval_t, i );
150
+ if ( 0L == i->start_instant ) {
151
+ rb_raise(eH_Error, "Attempt to stop an interval that has not started.\n" );
152
+ }
153
+
154
+ if ( 0L == i->stop_instant ) {
155
+ double d;
156
+
157
+ i->stop_instant = hitimes_get_current_instant( );
158
+ d = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
159
+ i->duration = rb_float_new( d );
160
+ rb_gc_register_address( &(i->duration) );
161
+ rc = i->duration;
162
+ }
163
+
164
+ return rc;
165
+ }
166
+
167
+ /**
168
+ * call-seq:
169
+ * interval.started? -> boolean
170
+ *
171
+ * returns whether or not the interval has been started
172
+ */
173
+ VALUE hitimes_interval_started( VALUE self )
174
+ {
175
+ hitimes_interval_t *i;
176
+
177
+ Data_Get_Struct( self, hitimes_interval_t, i );
178
+
179
+ return ( 0L == i->start_instant ) ? Qfalse : Qtrue;
180
+ }
181
+
182
+
183
+ /**
184
+ * call-seq:
185
+ * interval.stopped? -> boolean
186
+ *
187
+ * returns whether or not the interval has been stopped
188
+ */
189
+ VALUE hitimes_interval_stopped( VALUE self )
190
+ {
191
+ hitimes_interval_t *i;
192
+
193
+ Data_Get_Struct( self, hitimes_interval_t, i );
194
+
195
+ return ( 0L == i->stop_instant ) ? Qfalse : Qtrue;
196
+ }
197
+
198
+ /**
199
+ * call-seq:
200
+ * interval.running? -> boolean
201
+ *
202
+ * returns whether or not the interval is running or not. This means that it
203
+ * has started, but not stopped.
204
+ */
205
+ VALUE hitimes_interval_running( VALUE self )
206
+ {
207
+ hitimes_interval_t *i;
208
+ VALUE rc = Qfalse;
209
+
210
+ Data_Get_Struct( self, hitimes_interval_t, i );
211
+ if ( ( 0L != i->start_instant ) && ( 0L == i->stop_instant ) ) {
212
+ rc = Qtrue;
213
+ }
214
+
215
+ return rc;
216
+ }
217
+
218
+
219
+ /**
220
+ * call-seq:
221
+ * interval.start_instant -> Integer
222
+ *
223
+ * The integer representing the start instant of the Interval. This value
224
+ * is not useful on its own. It is a platform dependent value.
225
+ */
226
+ VALUE hitimes_interval_start_instant( VALUE self )
227
+ {
228
+ hitimes_interval_t *i;
229
+
230
+ Data_Get_Struct( self, hitimes_interval_t, i );
231
+
232
+ return ULL2NUM( i->start_instant );
233
+ }
234
+
235
+
236
+ /**
237
+ * call-seq:
238
+ * interval.stop_instant -> Integer
239
+ *
240
+ * The integer representing the stop instant of the Interval. This value
241
+ * is not useful on its own. It is a platform dependent value.
242
+ */
243
+ VALUE hitimes_interval_stop_instant( VALUE self )
244
+ {
245
+ hitimes_interval_t *i;
246
+
247
+ Data_Get_Struct( self, hitimes_interval_t, i );
248
+
249
+ return ULL2NUM( i->stop_instant );
250
+ }
251
+
252
+
253
+
254
+ /**
255
+ * call-seq:
256
+ * interval.duration -> Float
257
+ *
258
+ * Returns the Float value of the interval, the value is in seconds. If the
259
+ * interval has not had stop called yet, it will report the number of seconds
260
+ * in the interval up to the current point in time.
261
+ */
262
+ VALUE hitimes_interval_duration ( VALUE self )
263
+ {
264
+ hitimes_interval_t *i;
265
+ double d;
266
+
267
+ Data_Get_Struct( self, hitimes_interval_t, i );
268
+
269
+ /**
270
+ * if stop has not yet been called, then return the amount of time so far
271
+ */
272
+ if ( 0L == i->stop_instant ) {
273
+ hitimes_instant_t now = hitimes_get_current_instant( );
274
+ d = ( now - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
275
+ return rb_float_new( d );
276
+ }
277
+
278
+
279
+ /*
280
+ * stop has been called, calculate the duration and save the result
281
+ */
282
+ if ( Qnil == i->duration ) {
283
+ d = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
284
+ i->duration = rb_float_new( d );
285
+ rb_gc_register_address( &(i->duration) );
286
+ }
287
+
288
+ return i->duration;
289
+ }
290
+
291
+
292
+ /**
293
+ * Document-class: Hitimes::Interval
294
+ *
295
+ * This is the lowest level timing mechanism available. It allows for easy
296
+ * measuring based upon a block:
297
+ *
298
+ * duration = Interval.measure { ... }
299
+ *
300
+ * Or measuring something specifically
301
+ *
302
+ * interval = Interval.new
303
+ * interval.start
304
+ * duration = interval.stop
305
+ *
306
+ * Allocating and starting an interval can be done in one method call with
307
+ *
308
+ * interval = Interval.now
309
+ *
310
+ * Interval is useful when you only need to track a single interval of time, or
311
+ * if you do not want to track statistics about an operation.
312
+ *
313
+ */
314
+ void Init_hitimes_interval()
315
+ {
316
+ mH = rb_define_module("Hitimes");
317
+
318
+ cH_Interval = rb_define_class_under( mH, "Interval", rb_cObject );
319
+ rb_define_alloc_func( cH_Interval, hitimes_interval_alloc );
320
+
321
+ rb_define_module_function( cH_Interval, "now", hitimes_interval_now, 0 ); /* in hitimes_interval.c */
322
+ rb_define_module_function( cH_Interval, "measure", hitimes_interval_measure, 0 ); /* in hitimes_interval.c */
323
+
324
+ rb_define_method( cH_Interval, "to_f", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
325
+ rb_define_method( cH_Interval, "to_seconds", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
326
+ rb_define_method( cH_Interval, "duration", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
327
+ rb_define_method( cH_Interval, "length", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
328
+
329
+ rb_define_method( cH_Interval, "started?", hitimes_interval_started, 0 ); /* in hitimes_interval.c */
330
+ rb_define_method( cH_Interval, "running?", hitimes_interval_running, 0 ); /* in hitimes_interval.c */
331
+ rb_define_method( cH_Interval, "stopped?", hitimes_interval_stopped, 0 ); /* in hitimes_interval.c */
332
+
333
+ rb_define_method( cH_Interval, "start_instant", hitimes_interval_start_instant, 0 ); /* in hitimes_interval.c */
334
+ rb_define_method( cH_Interval, "stop_instant", hitimes_interval_stop_instant, 0 ); /* in hitimes_interval.c */
335
+
336
+ rb_define_method( cH_Interval, "start", hitimes_interval_start, 0); /* in hitimes_interval.c */
337
+ rb_define_method( cH_Interval, "stop", hitimes_interval_stop, 0); /* in hitimes_interval.c */
338
+ rb_define_method( cH_Interval, "split", hitimes_interval_split, 0); /* in hitimes_interval.c */
339
+
340
+ }