hitimes 0.3.0-x86-mswin32-60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }