hitimes 1.3.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +57 -0
  3. data/HISTORY.md +124 -0
  4. data/LICENSE +16 -0
  5. data/Manifest.txt +44 -0
  6. data/README.md +200 -0
  7. data/Rakefile +28 -0
  8. data/examples/benchmarks.rb +113 -0
  9. data/examples/stats.rb +31 -0
  10. data/ext/hitimes/c/extconf.rb +24 -0
  11. data/ext/hitimes/c/hitimes.c +37 -0
  12. data/ext/hitimes/c/hitimes_instant_clock_gettime.c +28 -0
  13. data/ext/hitimes/c/hitimes_instant_osx.c +45 -0
  14. data/ext/hitimes/c/hitimes_instant_windows.c +27 -0
  15. data/ext/hitimes/c/hitimes_interval.c +370 -0
  16. data/ext/hitimes/c/hitimes_interval.h +73 -0
  17. data/ext/hitimes/c/hitimes_stats.c +269 -0
  18. data/ext/hitimes/c/hitimes_stats.h +30 -0
  19. data/ext/hitimes/java/src/hitimes/Hitimes.java +66 -0
  20. data/ext/hitimes/java/src/hitimes/HitimesInterval.java +176 -0
  21. data/ext/hitimes/java/src/hitimes/HitimesService.java +16 -0
  22. data/ext/hitimes/java/src/hitimes/HitimesStats.java +112 -0
  23. data/lib/hitimes.rb +66 -0
  24. data/lib/hitimes/2.0/hitimes.so +0 -0
  25. data/lib/hitimes/2.1/hitimes.so +0 -0
  26. data/lib/hitimes/2.2/hitimes.so +0 -0
  27. data/lib/hitimes/2.3/hitimes.so +0 -0
  28. data/lib/hitimes/2.4/hitimes.so +0 -0
  29. data/lib/hitimes/2.5/hitimes.so +0 -0
  30. data/lib/hitimes/metric.rb +118 -0
  31. data/lib/hitimes/mutexed_stats.rb +32 -0
  32. data/lib/hitimes/paths.rb +53 -0
  33. data/lib/hitimes/stats.rb +58 -0
  34. data/lib/hitimes/timed_metric.rb +176 -0
  35. data/lib/hitimes/timed_value_metric.rb +233 -0
  36. data/lib/hitimes/value_metric.rb +71 -0
  37. data/lib/hitimes/version.rb +8 -0
  38. data/spec/hitimes_spec.rb +24 -0
  39. data/spec/interval_spec.rb +136 -0
  40. data/spec/metric_spec.rb +28 -0
  41. data/spec/mutex_stats_spec.rb +36 -0
  42. data/spec/paths_spec.rb +11 -0
  43. data/spec/spec_helper.rb +11 -0
  44. data/spec/stats_spec.rb +98 -0
  45. data/spec/timed_metric_spec.rb +155 -0
  46. data/spec/timed_value_metric_spec.rb +171 -0
  47. data/spec/value_metric_spec.rb +108 -0
  48. data/spec/version_spec.rb +7 -0
  49. data/tasks/default.rake +242 -0
  50. data/tasks/extension.rake +38 -0
  51. data/tasks/this.rb +208 -0
  52. metadata +216 -0
@@ -0,0 +1,28 @@
1
+ # vim: syntax=ruby
2
+ load 'tasks/this.rb'
3
+
4
+ This.name = "hitimes"
5
+ This.author = "Jeremy Hinegardner"
6
+ This.email = "jeremy@copiousfreetime.org"
7
+ This.homepage = "http://github.com/copiousfreetime/#{ This.name }"
8
+
9
+ This.ruby_gemspec do |spec|
10
+ spec.add_development_dependency( 'rake' , '~> 12.0')
11
+ spec.add_development_dependency( 'minitest' , '~> 5.5' )
12
+ spec.add_development_dependency( 'rdoc' , '~> 5.0' )
13
+ spec.add_development_dependency( 'json' , '~> 2.0' )
14
+ spec.add_development_dependency( 'rake-compiler', '~> 1.0' )
15
+ spec.add_development_dependency( 'rake-compiler-dock', '~> 0.6' )
16
+ spec.add_development_dependency( 'simplecov' , '~> 0.14' )
17
+
18
+ spec.extensions.concat This.extension_conf_files
19
+ spec.license = "ISC"
20
+ end
21
+
22
+ This.java_gemspec( This.ruby_gemspec ) do |spec|
23
+ spec.extensions.clear
24
+ spec.files << "lib/hitimes/hitimes.jar"
25
+ end
26
+
27
+ load 'tasks/default.rake'
28
+ load 'tasks/extension.rake'
@@ -0,0 +1,113 @@
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::TimedMetric.now('duration_t1').stop
48
+ end
49
+
50
+ #
51
+ # reuse the same timer over and over
52
+ #
53
+ HT2= Hitimes::TimedMetric.new( 'duration_t2' )
54
+ def hitimes_duration_t2
55
+ HT2.start
56
+ HT2.stop
57
+ end
58
+
59
+ HT3 = Hitimes::TimedMetric.new( 'duration_t3' )
60
+ def hitimes_duration_t3
61
+ HT3.measure { nil }
62
+ end
63
+
64
+ #
65
+ # Check out the speed of the TimedValueMetric too
66
+ #
67
+ def hitimes_duration_tv1
68
+ Hitimes::TimedValueMetric.now( 'duration_tv1' ).stop( 42 )
69
+ end
70
+
71
+ HTV2 = Hitimes::TimedValueMetric.new( 'duration_tv2' )
72
+ def hitimes_duration_tv2
73
+ HTV2.start
74
+ HTV2.stop( 42 )
75
+ end
76
+
77
+ HTV3 = Hitimes::TimedValueMetric.new( 'duration_tv3' )
78
+ def hitimes_duration_tv3
79
+ HTV3.measure( 42 ) { nil }
80
+ end
81
+
82
+ #
83
+ # use the Struct::Tms values and return the difference in User time between 2
84
+ # successive calls
85
+ #
86
+ def process_duration
87
+ t1 = Process.times.utime
88
+ Process.times.utime - t1
89
+ end
90
+
91
+ #
92
+ # Take 2 times and subtract one from the other
93
+ #
94
+ def time_duration
95
+ t1 = Time.now.to_f
96
+ Time.now.to_f - t1
97
+ end
98
+
99
+
100
+ puts "Testing time sampling 100,000 times"
101
+
102
+ bm(30) do |x|
103
+ x.report("Process") { 100_000.times { process_duration } }
104
+ x.report("Time") { 100_000.times { time_duration } }
105
+ x.report("Hitimes::TimedMetric 1") { 100_000.times { hitimes_duration_t1 } }
106
+ x.report("Hitimes::TimedMetric 2") { 100_000.times { hitimes_duration_t2 } }
107
+ x.report("Hitimes::TimedMetric 3") { 100_000.times { hitimes_duration_t3 } }
108
+ x.report("Hitimes::Interval 1") { 100_000.times { hitimes_duration_i1 } }
109
+ x.report("Hitimes::Interval 2") { 100_000.times { hitimes_duration_i2 } }
110
+ x.report("Hitimes::TimedValueMetric 1") { 100_000.times { hitimes_duration_tv1 } }
111
+ x.report("Hitimes::TimedValueMetric 2") { 100_000.times { hitimes_duration_tv2 } }
112
+ x.report("Hitimes::TimedValueMetric 3") { 100_000.times { hitimes_duration_tv3 } }
113
+ end
@@ -0,0 +1,31 @@
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
+ Hitimes::Stats::STATS.each do |m|
27
+ puts "#{m.rjust(6)} : #{s.send( m ) }"
28
+ end
29
+
30
+ puts s.to_hash.inspect
31
+
@@ -0,0 +1,24 @@
1
+ require 'rbconfig'
2
+ require 'mkmf'
3
+
4
+ if RbConfig::CONFIG['host_os'] =~ /darwin/ then
5
+ $CFLAGS += " -DUSE_INSTANT_OSX=1 -Wall"
6
+ $LDFLAGS += " -framework CoreServices"
7
+ elsif RbConfig::CONFIG['host_os'] =~ /win(32|64)/ or RbConfig::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
+ elsif have_library("c", "clock_gettime") then
13
+ $CFLAGS += " -DUSE_INSTANT_CLOCK_GETTIME=1"
14
+ else
15
+ raise NotImplementedError, <<-_
16
+ Unable to find the function 'clock_gettime' in either libc or librt.
17
+ Please file an issue at https://github.com/copiousfreetime/hitimes.
18
+ _
19
+ end
20
+ end
21
+
22
+ # put in a different location if on windows so we can have fat binaries
23
+ subdir = RUBY_VERSION.gsub(/\.\d+$/,'')
24
+ create_makefile("hitimes/#{subdir}/hitimes")
@@ -0,0 +1,37 @@
1
+ #include <ruby.h>
2
+ #include "hitimes_interval.h"
3
+
4
+ /* Module and Classes */
5
+ VALUE mH; /* module Hitimes */
6
+ VALUE eH_Error; /* class Hitimes::Error */
7
+
8
+
9
+ /**
10
+ * call-seq:
11
+ * Hitimes.raw_instant -> Integer
12
+ *
13
+ * Return the raw instant value from the operating system
14
+ */
15
+ VALUE hitimes_instant_raw( )
16
+ {
17
+ unsigned long long i = (unsigned long long)hitimes_get_current_instant( );
18
+
19
+ return ULL2NUM(i);
20
+ }
21
+
22
+ /*
23
+ * Document-class: Hitimes::Error
24
+ *
25
+ * General error class for the Hitimes module
26
+ */
27
+ void Init_hitimes( )
28
+ {
29
+ mH = rb_define_module("Hitimes");
30
+
31
+ eH_Error = rb_define_class_under(mH, "Error", rb_eStandardError);
32
+ rb_define_const( mH, "INSTANT_CONVERSION_FACTOR", DBL2NUM( HITIMES_INSTANT_CONVERSION_FACTOR ));
33
+ rb_define_module_function( mH, "raw_instant", hitimes_instant_raw, 0 );
34
+
35
+ Init_hitimes_interval();
36
+ Init_hitimes_stats( );
37
+ }
@@ -0,0 +1,28 @@
1
+ #ifdef USE_INSTANT_CLOCK_GETTIME
2
+
3
+ #include "hitimes_interval.h"
4
+
5
+ #include <time.h>
6
+ #ifndef CLOCK_MONOTONIC
7
+ # include <sys/time.h>
8
+ # ifndef CLOCK_MONOTONIC
9
+ # ifdef __linux__
10
+ # include <linux/time.h>
11
+ # endif
12
+ # endif
13
+ #endif
14
+
15
+ hitimes_instant_t hitimes_get_current_instant( )
16
+ {
17
+ struct timespec time;
18
+ int rc;
19
+
20
+ rc = clock_gettime( CLOCK_MONOTONIC, &time);
21
+ if ( 0 != rc ) {
22
+ char* e = strerror( rc );
23
+ rb_raise(eH_Error, "Unable to retrieve time for CLOCK_MONOTONIC : %s", e );
24
+ }
25
+
26
+ return ( ( NANOSECONDS_PER_SECOND * (long)time.tv_sec ) + time.tv_nsec );
27
+ }
28
+ #endif
@@ -0,0 +1,45 @@
1
+ #ifdef USE_INSTANT_OSX
2
+
3
+ #include "hitimes_interval.h"
4
+ #include <mach/mach.h>
5
+ #include <mach/mach_time.h>
6
+
7
+ /* All this OSX code is adapted from http://developer.apple.com/library/mac/#qa/qa1398/_index.html */
8
+
9
+ /*
10
+ * returns the conversion factor, this value is used to convert
11
+ * the value from hitimes_get_current_instant() into seconds
12
+ */
13
+ long double hitimes_instant_conversion_factor()
14
+ {
15
+ static mach_timebase_info_data_t s_timebase_info;
16
+ static long double conversion_factor;
17
+ static uint64_t nano_conversion;
18
+
19
+ /**
20
+ * If this is the first time we've run, get the timebase.
21
+ * We can use denom == 0 to indicate that s_timebase_info is
22
+ * uninitialised because it makes no sense to have a zero
23
+ * denominator is a fraction.
24
+ */
25
+
26
+ if ( s_timebase_info.denom == 0 ) {
27
+ mach_timebase_info(&s_timebase_info);
28
+ nano_conversion = s_timebase_info.numer / s_timebase_info.denom;
29
+ conversion_factor = (long double) (nano_conversion) * (1e9l);
30
+ }
31
+
32
+ return conversion_factor;
33
+ }
34
+
35
+ /*
36
+ * returns the mach absolute time, which has no meaning outside of a conversion
37
+ * factor.
38
+ */
39
+ hitimes_instant_t hitimes_get_current_instant()
40
+ {
41
+ return mach_absolute_time();
42
+ }
43
+
44
+
45
+ #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
+ long 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,370 @@
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
+ xfree( i );
20
+ return Qnil;
21
+ }
22
+
23
+ VALUE hitimes_interval_alloc(VALUE klass)
24
+ {
25
+ VALUE obj;
26
+ hitimes_interval_t* i = xmalloc( sizeof( hitimes_interval_t ) );
27
+
28
+ i->start_instant = 0L;
29
+ i->stop_instant = 0L;
30
+ i->duration = -1.0l;
31
+
32
+ obj = Data_Wrap_Struct(klass, NULL, hitimes_interval_free, i);
33
+ return obj;
34
+ }
35
+
36
+ /**
37
+ * call-seq:
38
+ * Interval.now -> Interval
39
+ *
40
+ * Create an interval that has already started
41
+ */
42
+ VALUE hitimes_interval_now( )
43
+ {
44
+ VALUE obj;
45
+ hitimes_interval_t *i = xmalloc( sizeof( hitimes_interval_t ) );
46
+
47
+ i->start_instant = hitimes_get_current_instant( );
48
+ i->stop_instant = 0L;
49
+ i->duration = -1.0l;
50
+
51
+ obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, i);
52
+
53
+ return obj;
54
+ }
55
+
56
+ /**
57
+ * call-seq:
58
+ * Interval.measure { } -> Float
59
+ *
60
+ * Times the execution of the block returning the number of seconds it took
61
+ */
62
+ VALUE hitimes_interval_measure( )
63
+ {
64
+ hitimes_instant_t before;
65
+ hitimes_instant_t after;
66
+ long double duration;
67
+
68
+ if ( !rb_block_given_p() ) {
69
+ rb_raise(eH_Error, "No block given to Interval.measure" );
70
+ }
71
+
72
+ before = hitimes_get_current_instant( );
73
+ rb_yield( Qnil );
74
+ after = hitimes_get_current_instant( );
75
+
76
+ duration = ( after - before ) / HITIMES_INSTANT_CONVERSION_FACTOR;
77
+ return rb_float_new( duration );
78
+ }
79
+
80
+ /**
81
+ * call-seq:
82
+ * interval.split -> Interval
83
+ *
84
+ * Immediately stop the current interval and start a new interval that has a
85
+ * start_instant equivalent to the stop_interval of self.
86
+ */
87
+ VALUE hitimes_interval_split( VALUE self )
88
+ {
89
+ hitimes_interval_t *first;
90
+ hitimes_interval_t *second = xmalloc( sizeof( hitimes_interval_t ) );
91
+ VALUE obj;
92
+
93
+ Data_Get_Struct( self, hitimes_interval_t, first );
94
+ first->stop_instant = hitimes_get_current_instant( );
95
+
96
+ second->start_instant = first->stop_instant;
97
+ second->stop_instant = 0L;
98
+ second->duration = -1.0l;
99
+
100
+ obj = Data_Wrap_Struct(cH_Interval, NULL, hitimes_interval_free, second);
101
+
102
+ return obj;
103
+ }
104
+
105
+
106
+ /**
107
+ * call-seq:
108
+ * interval.start -> boolean
109
+ *
110
+ * mark the start of the interval. Calling start on an already started
111
+ * interval has no effect. An interval can only be started once. If the
112
+ * interval is truely started +true+ is returned otherwise +false+.
113
+ */
114
+ VALUE hitimes_interval_start( VALUE self )
115
+ {
116
+ hitimes_interval_t *i;
117
+ VALUE rc = Qfalse;
118
+
119
+ Data_Get_Struct( self, hitimes_interval_t, i );
120
+ if ( 0L == i->start_instant ) {
121
+ i->start_instant = hitimes_get_current_instant( );
122
+ i->stop_instant = 0L;
123
+ i->duration = -1.0l;
124
+
125
+ rc = Qtrue;
126
+ }
127
+
128
+ return rc;
129
+ }
130
+
131
+
132
+ /**
133
+ * call-seq:
134
+ * interval.stop -> bool or Float
135
+ *
136
+ * mark the stop of the interval. Calling stop on an already stopped interval
137
+ * has no effect. An interval can only be stopped once. If the interval is
138
+ * truely stopped then the duration is returned, otherwise +false+.
139
+ */
140
+ VALUE hitimes_interval_stop( VALUE self )
141
+ {
142
+ hitimes_interval_t *i;
143
+ VALUE rc = Qfalse;
144
+
145
+ Data_Get_Struct( self, hitimes_interval_t, i );
146
+ if ( 0L == i->start_instant ) {
147
+ rb_raise(eH_Error, "Attempt to stop an interval that has not started" );
148
+ }
149
+
150
+ if ( 0L == i->stop_instant ) {
151
+ i->stop_instant = hitimes_get_current_instant( );
152
+ i->duration = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
153
+ rc = rb_float_new( i->duration );
154
+ }
155
+
156
+ return rc;
157
+ }
158
+
159
+ /**
160
+ * call-seq:
161
+ * interval.duration_so_far -> Float or false
162
+ *
163
+ * return how the duration so far. This will return the duration from the time
164
+ * the Interval was started if the interval is running, otherwise it will return
165
+ * false.
166
+ */
167
+ VALUE hitimes_interval_duration_so_far( VALUE self )
168
+ {
169
+ hitimes_interval_t *i;
170
+ VALUE rc = Qfalse;
171
+
172
+ Data_Get_Struct( self, hitimes_interval_t, i );
173
+ if ( 0L == i->start_instant ) {
174
+ return rc;
175
+ }
176
+
177
+ if ( 0L == i->stop_instant ) {
178
+ long double d;
179
+ hitimes_instant_t now = hitimes_get_current_instant( );
180
+ d = ( now - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
181
+ rc = rb_float_new( d );
182
+ }
183
+ return rc;
184
+ }
185
+
186
+
187
+ /**
188
+ * call-seq:
189
+ * interval.started? -> boolean
190
+ *
191
+ * returns whether or not the interval has been started
192
+ */
193
+ VALUE hitimes_interval_started( VALUE self )
194
+ {
195
+ hitimes_interval_t *i;
196
+
197
+ Data_Get_Struct( self, hitimes_interval_t, i );
198
+
199
+ return ( 0L == i->start_instant ) ? Qfalse : Qtrue;
200
+ }
201
+
202
+
203
+ /**
204
+ * call-seq:
205
+ * interval.stopped? -> boolean
206
+ *
207
+ * returns whether or not the interval has been stopped
208
+ */
209
+ VALUE hitimes_interval_stopped( VALUE self )
210
+ {
211
+ hitimes_interval_t *i;
212
+
213
+ Data_Get_Struct( self, hitimes_interval_t, i );
214
+
215
+ return ( 0L == i->stop_instant ) ? Qfalse : Qtrue;
216
+ }
217
+
218
+ /**
219
+ * call-seq:
220
+ * interval.running? -> boolean
221
+ *
222
+ * returns whether or not the interval is running or not. This means that it
223
+ * has started, but not stopped.
224
+ */
225
+ VALUE hitimes_interval_running( VALUE self )
226
+ {
227
+ hitimes_interval_t *i;
228
+ VALUE rc = Qfalse;
229
+
230
+ Data_Get_Struct( self, hitimes_interval_t, i );
231
+ if ( ( 0L != i->start_instant ) && ( 0L == i->stop_instant ) ) {
232
+ rc = Qtrue;
233
+ }
234
+
235
+ return rc;
236
+ }
237
+
238
+
239
+ /**
240
+ * call-seq:
241
+ * interval.start_instant -> Integer
242
+ *
243
+ * The integer representing the start instant of the Interval. This value
244
+ * is not useful on its own. It is a platform dependent value.
245
+ */
246
+ VALUE hitimes_interval_start_instant( VALUE self )
247
+ {
248
+ hitimes_interval_t *i;
249
+
250
+ Data_Get_Struct( self, hitimes_interval_t, i );
251
+
252
+ return ULL2NUM( i->start_instant );
253
+ }
254
+
255
+
256
+ /**
257
+ * call-seq:
258
+ * interval.stop_instant -> Integer
259
+ *
260
+ * The integer representing the stop instant of the Interval. This value
261
+ * is not useful on its own. It is a platform dependent value.
262
+ */
263
+ VALUE hitimes_interval_stop_instant( VALUE self )
264
+ {
265
+ hitimes_interval_t *i;
266
+
267
+ Data_Get_Struct( self, hitimes_interval_t, i );
268
+
269
+ return ULL2NUM( i->stop_instant );
270
+ }
271
+
272
+
273
+
274
+ /**
275
+ * call-seq:
276
+ * interval.duration -> Float
277
+ * interval.to_f -> Float
278
+ * interval.to_seconds -> Float
279
+ * interval.length -> Float
280
+ *
281
+ * Returns the Float value of the interval, the value is in seconds. If the
282
+ * interval has not had stop called yet, it will report the number of seconds
283
+ * in the interval up to the current point in time.
284
+ *
285
+ * Raises Error if duration is called on an interval that has not started yet.
286
+ */
287
+ VALUE hitimes_interval_duration ( VALUE self )
288
+ {
289
+ hitimes_interval_t *i;
290
+
291
+ Data_Get_Struct( self, hitimes_interval_t, i );
292
+
293
+ /* raise an error if the internval is not started */
294
+ if ( 0L == i->start_instant ) {
295
+ rb_raise(eH_Error, "Attempt to report a duration on an interval that has not started" );
296
+ }
297
+
298
+
299
+ /**
300
+ * if stop has not yet been called, then return the amount of time so far
301
+ */
302
+ if ( 0L == i->stop_instant ) {
303
+ long double d;
304
+ hitimes_instant_t now = hitimes_get_current_instant( );
305
+ d = ( now - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
306
+ return rb_float_new( d );
307
+ }
308
+
309
+ /*
310
+ * stop has been called, calculate the duration and save the result
311
+ */
312
+ if ( i->duration < 0.0 ) {
313
+ i->duration = ( i->stop_instant - i->start_instant ) / HITIMES_INSTANT_CONVERSION_FACTOR;
314
+ }
315
+
316
+ return rb_float_new( i->duration );
317
+ }
318
+
319
+
320
+ /**
321
+ * Document-class: Hitimes::Interval
322
+ *
323
+ * This is the lowest level timing mechanism available. It allows for easy
324
+ * measuring based upon a block:
325
+ *
326
+ * duration = Interval.measure { ... }
327
+ *
328
+ * Or measuring something specifically
329
+ *
330
+ * interval = Interval.new
331
+ * interval.start
332
+ * duration = interval.stop
333
+ *
334
+ * Allocating and starting an interval can be done in one method call with
335
+ *
336
+ * interval = Interval.now
337
+ *
338
+ * Interval is useful when you only need to track a single interval of time, or
339
+ * if you do not want to track statistics about an operation.
340
+ *
341
+ */
342
+ void Init_hitimes_interval()
343
+ {
344
+ mH = rb_define_module("Hitimes");
345
+
346
+ cH_Interval = rb_define_class_under( mH, "Interval", rb_cObject );
347
+ rb_define_alloc_func( cH_Interval, hitimes_interval_alloc );
348
+
349
+ rb_define_module_function( cH_Interval, "now", hitimes_interval_now, 0 ); /* in hitimes_interval.c */
350
+ rb_define_module_function( cH_Interval, "measure", hitimes_interval_measure, 0 ); /* in hitimes_interval.c */
351
+
352
+ rb_define_method( cH_Interval, "duration", hitimes_interval_duration, 0 ); /* in hitimes_interval.c */
353
+ rb_define_method( cH_Interval, "length", hitimes_interval_duration, 0 );
354
+ rb_define_method( cH_Interval, "to_f", hitimes_interval_duration, 0 );
355
+ rb_define_method( cH_Interval, "to_seconds", hitimes_interval_duration, 0 );
356
+
357
+ rb_define_method( cH_Interval, "duration_so_far", hitimes_interval_duration_so_far, 0); /* in hitimes_interval.c */
358
+
359
+ rb_define_method( cH_Interval, "started?", hitimes_interval_started, 0 ); /* in hitimes_interval.c */
360
+ rb_define_method( cH_Interval, "running?", hitimes_interval_running, 0 ); /* in hitimes_interval.c */
361
+ rb_define_method( cH_Interval, "stopped?", hitimes_interval_stopped, 0 ); /* in hitimes_interval.c */
362
+
363
+ rb_define_method( cH_Interval, "start_instant", hitimes_interval_start_instant, 0 ); /* in hitimes_interval.c */
364
+ rb_define_method( cH_Interval, "stop_instant", hitimes_interval_stop_instant, 0 ); /* in hitimes_interval.c */
365
+
366
+ rb_define_method( cH_Interval, "start", hitimes_interval_start, 0); /* in hitimes_interval.c */
367
+ rb_define_method( cH_Interval, "stop", hitimes_interval_stop, 0); /* in hitimes_interval.c */
368
+ rb_define_method( cH_Interval, "split", hitimes_interval_split, 0); /* in hitimes_interval.c */
369
+
370
+ }