monotime 0.7.1 → 0.8.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8a9395967e506d690912041251bc7b6afd1a373aa49d0b4425ec08ca611e5238
4
- data.tar.gz: '09ec6a1e96c9ce434d4847d275d85f7514c4a9bb3d9c71d205b04ab0f06e6d5b'
3
+ metadata.gz: 207159be0c76004c8676ac860106cd133344a29ca0021decbc14bc7448a17fab
4
+ data.tar.gz: 89c97583a40bfe82dd7c822cfd9a165be19c796cdf32396ee49ef861bbf7fb32
5
5
  SHA512:
6
- metadata.gz: a68a338484a8534a8953abf5bec0a98a6b7a2dc6a506cd1f5fb1e3b29e1b534fa0d41e4175aa81598273ee5d706d16caeb60ce1b89a92b5e8192f87a960265f3
7
- data.tar.gz: f9f329d74339eccc1b4c50007d2cb93cc87132ce6a5841faa327d4db48dfb347df8faee3f9777551cb686e90001def65d72c8a77c6b6df4dfed1d847598ac685
6
+ metadata.gz: c3aa917f832adedaa98acca61c58858d9e4ce57922d3ba457921b2e2c8adc023875a328c308258555f38dbb482168da73f7488c6306bd9751089b3ef21f5e7b0
7
+ data.tar.gz: b340008fa59637177c6c3caad1d4f5816ba8626a533993d3cc8de615b4c12899b3939e4338f6dae04d66fa09c90e6d7de06667cd02af915c2717bef7fca9aa25
@@ -2,13 +2,14 @@ name: CI
2
2
  on: [push, pull_request]
3
3
  jobs:
4
4
  test:
5
- runs-on: ubuntu-latest
6
5
  strategy:
7
6
  fail-fast: false
8
7
  matrix:
9
- ruby: ['2.5', '2.6', '2.7', '3.0', jruby, truffleruby]
8
+ os: [ubuntu-latest, macos-latest]
9
+ ruby: ['2.7', '3.0', '3.1', '3.2', head, jruby, jruby-head, truffleruby, truffleruby-head]
10
+ runs-on: ${{ matrix.os }}
10
11
  steps:
11
- - uses: actions/checkout@v2
12
+ - uses: actions/checkout@v4
12
13
  - uses: ruby/setup-ruby@v1
13
14
  with:
14
15
  ruby-version: ${{ matrix.ruby }}
data/.rubocop.yml CHANGED
@@ -11,7 +11,10 @@ Layout/LineLength:
11
11
  Max: 96
12
12
 
13
13
  Metrics/ClassLength:
14
- Max: 120
14
+ Max: 140
15
+
16
+ Metrics/MethodLength:
17
+ Max: 20
15
18
 
16
19
  Style/AsciiComments:
17
20
  Enabled: false
@@ -36,3 +39,6 @@ Style/ExplicitBlockArgument:
36
39
 
37
40
  Style/MixinUsage:
38
41
  Enabled: false
42
+
43
+ Style/TrailingCommaInArrayLiteral:
44
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,100 +1,172 @@
1
1
  # Changelog
2
2
 
3
- ## 0.7.1 - 2021-10-22
3
+ ## [0.8.1] - 2023-09-18
4
+
5
+ ### Changed
6
+
7
+ - After further consideration, return to defaulting to `CLOCK_MONOTONIC` instead
8
+ of the overly-elaborate auto-selection introduced in 0.8.0.
9
+
10
+ ### Removed
11
+
12
+ - `Instant.clock_name`. No I'm not incrementing to 0.9. It's been a few hours,
13
+ you're not using it, shut up.
14
+
15
+ ## [0.8.0] - 2023-09-17
16
+
4
17
  ### Added
5
- - `simplecov` introduced to test suite.
6
- - `monotime/include.rb` to auto-include types globally.
18
+
19
+ - Default precision for `Duration#to_s` can be set using
20
+ `Duration.default_to_s_precision=`.
21
+ - Default sleep function can be set using `Duration.sleep_function=`
22
+ - `Duration::ZERO` and `Duration.zero` for an easy, memory-efficient
23
+ zero-duration singleton.
24
+ - `Instant.clock_id` and `Instant.clock_id=` to control the default clock
25
+ source.
26
+ - `Instant.clock_getres` to get the minimum supported `Duration` from the
27
+ selected clock source.
28
+ - `Instant.monotonic_function=` to completely replace the default monotonic
29
+ function.
7
30
 
8
31
  ### Changed
9
- - All `Instant` and `Duration` instances are now frozen.
10
- - Migrate from Travis CI to Github Actions
11
- - Update development dependency on `rake`.
32
+
33
+ - The default clock source is now chosen from a selection of options instead of
34
+ defaulting to `CLOCK_MONOTONIC``. Where possible options are used which are
35
+ unaffected by NTP frequency skew and which do not count time in system suspend.
36
+ - CI matrix drops Ruby 2.5 and 2.6 and adds 3.1, 3.2, head branches of Ruby,
37
+ JRuby, and TruffleRuby, and also tests under macOS.
38
+
39
+ ### Fixed
40
+
41
+ - CI on TruffleRuby has been fixed by disabling SimpleCov.
42
+ - Several fragile tests depending on relatively narrow sleep times have been fixed.
43
+
44
+ ### Thanks
45
+
46
+ - [@petergoldstein] for fixing CI on TruffleRuby and adding 3.1 and 3.2.
47
+ - [@fig] for fixing a README error.
48
+
49
+ ## [0.7.1] - 2021-10-22
50
+
51
+ ### Added
52
+
53
+ - `simplecov` introduced to test suite.
54
+ - `monotime/include.rb` to auto-include types globally.
55
+
56
+ ### Changed
57
+
58
+ - All `Instant` and `Duration` instances are now frozen.
59
+ - Migrate from Travis CI to Github Actions
60
+ - Update development dependency on `rake`.
12
61
 
13
62
  ## [0.7.0] - 2019-04-24
63
+
14
64
  ### Added
15
- - `Duration.with_measure`, which yields and returns an array containing its
16
- evaluated return value and its `Duration`.
65
+
66
+ - `Duration.with_measure`, which yields and returns an array containing its
67
+ evaluated return value and its `Duration`.
17
68
 
18
69
  ### Changed
19
- - Break `Duration` and `Instant` into their own files.
20
- - Rename `Monotime::VERSION` to `Monotime::MONOTIME_VERSION` to reduce
21
- potential for collision if the module is included.
22
- - Update to bundler 2.0.
23
- - Rework README.md. Includes fix for [issue #1] (added a "See Also" section).
70
+
71
+ - Break `Duration` and `Instant` into their own files.
72
+ - Rename `Monotime::VERSION` to `Monotime::MONOTIME_VERSION` to reduce
73
+ potential for collision if the module is included.
74
+ - Update to bundler 2.0.
75
+ - Rework README.md. Includes fix for [issue #1] (added a "See Also" section).
24
76
 
25
77
  ## [0.6.1] - 2018-10-26
78
+
26
79
  ### Fixed
27
- - Build gem from a clean git checkout, not my local development directory.
28
- No functional changes.
80
+
81
+ - Build gem from a clean git checkout, not my local development directory.
82
+ No functional changes.
29
83
 
30
84
  ## [0.6.0] - 2018-10-26
85
+
31
86
  ### Added
32
- - This `CHANGELOG.md` by request of [@celsworth].
33
- - Aliases for `Duration.from_*` and `Duration#to_*` without the prefix. e.g.
34
- `Duration.from_secs(42).to_secs == 42` can now be written as
35
- `Duration.secs(42).secs == 42`.
36
- - `Duration#nonzero?`.
37
- - `Instant#in_past?` and `Instant#in_future?`.
87
+
88
+ - This `CHANGELOG.md` by request of [@celsworth].
89
+ - Aliases for `Duration.from_*` and `Duration#to_*` without the prefix. e.g.
90
+ `Duration.from_secs(42).to_secs == 42` can now be written as
91
+ `Duration.secs(42).secs == 42`.
92
+ - `Duration#nonzero?`.
93
+ - `Instant#in_past?` and `Instant#in_future?`.
38
94
 
39
95
  ## [0.5.0] - 2018-10-13
96
+
40
97
  ### Added
41
- - `Duration#abs` to make a `Duration` positive.
42
- - `Duration#-@` to invert the sign of a `Duration`.
43
- - `Duration#positive?`
44
- - `Duration#negative?`
45
- - `Duration#zero?`
98
+
99
+ - `Duration#abs` to make a `Duration` positive.
100
+ - `Duration#-@` to invert the sign of a `Duration`.
101
+ - `Duration#positive?`
102
+ - `Duration#negative?`
103
+ - `Duration#zero?`
46
104
 
47
105
  ### Changed
48
- - `Instant#sleep` with no argument now sleeps until the `Instant`.
49
- - `Duration.from_*` no longer coerce their argument to `Float`.
50
- - `Duration#==` checks value via `#to_nanos`, not type.
51
- - `Duration#eql?` checks value and type.
52
- - `Duration#<=>` compares value via `#to_nanos`.
106
+
107
+ - `Instant#sleep` with no argument now sleeps until the `Instant`.
108
+ - `Duration.from_*` no longer coerce their argument to `Float`.
109
+ - `Duration#==` checks value via `#to_nanos`, not type.
110
+ - `Duration#eql?` checks value and type.
111
+ - `Duration#<=>` compares value via `#to_nanos`.
53
112
 
54
113
  ## [0.4.0] - 2018-10-09
114
+
55
115
  ### Added
56
- - `Instant#sleep` - sleep to a given `Duration` past an `Instant`.
57
- - `Instant#sleep_secs` and `Instant#sleep_millis` convenience methods.
58
- - `Duration#sleep` - sleep for the `Duration`.
59
- - `Duration#*` - multiply a `Duration` by a number.
60
- - `Duration#/` - divide a `Duration` by a number.
116
+
117
+ - `Instant#sleep` - sleep to a given `Duration` past an `Instant`.
118
+ - `Instant#sleep_secs` and `Instant#sleep_millis` convenience methods.
119
+ - `Duration#sleep` - sleep for the `Duration`.
120
+ - `Duration#*` - multiply a `Duration` by a number.
121
+ - `Duration#/` - divide a `Duration` by a number.
61
122
 
62
123
  ### Changed
63
- - More `#to_nanos` `Duration` duck-typing.
124
+
125
+ More `#to_nanos` `Duration` duck-typing.
64
126
 
65
127
  ## [0.3.0] - 2018-10-04
128
+
66
129
  ### Added
67
- - `#to_nanos` is now used to duck-type `Duration` everywhere.
130
+
131
+ - `#to_nanos` is now used to duck-type `Duration` everywhere.
68
132
 
69
133
  ### Changed
70
- - Make `<=>` return nil on invalid types, rather than raising a `TypeError`.
134
+
135
+ - Make `<=>` return nil on invalid types, rather than raising a `TypeError`.
71
136
 
72
137
  ### Removed
73
- - Dependency on `dry-equalizer`.
138
+
139
+ - Dependency on `dry-equalizer`.
74
140
 
75
141
  ## [0.2.0] - 2018-10-03
142
+
76
143
  ### Added
77
- - `Instant#to_s` as an alias for `#elapsed.to_s`
78
- - `Duration#to_nanos`, with some limited duck-typing.
144
+
145
+ - `Instant#to_s` as an alias for `#elapsed.to_s`
146
+ - `Duration#to_nanos`, with some limited duck-typing.
79
147
 
80
148
  ### Changed
81
- - Switch to microseconds internally.
82
- - `Duration#to_{secs,millis,micros}` now return a `Float`.
83
- - `Instant#ns` is now `protected`.
149
+
150
+ - Switch to microseconds internally.
151
+ - `Duration#to_{secs,millis,micros}` now return a `Float`.
152
+ - `Instant#ns` is now `protected`.
84
153
 
85
154
  ### Fixed
86
- - `Duration#to_s` zero-stripping with precision=0.
87
- - `Instant#-` argument ordering with other `Instant`.
88
- - `Duration#to_micros` returns microseconds, not picoseconds.
155
+
156
+ - `Duration#to_s` zero-stripping with precision=0.
157
+ - `Instant#-` argument ordering with other `Instant`.
158
+ - `Duration#to_micros` returns microseconds, not picoseconds.
89
159
 
90
160
  ### Removed
91
- - `Instant` and `Duration` maths methods no longer support passing an `Integer`
92
- number of nanoseconds.
161
+
162
+ - `Instant` and `Duration` maths methods no longer support passing an `Integer`
163
+ number of nanoseconds.
93
164
 
94
165
  ## [0.1.0] - 2018-10-02
166
+
95
167
  ### Added
96
- - Initial release
97
168
 
169
+ - Initial release
98
170
 
99
171
  [0.1.0]: https://github.com/Freaky/monotime/commits/v0.1.0
100
172
  [0.2.0]: https://github.com/Freaky/monotime/commits/v0.2.0
@@ -104,5 +176,11 @@
104
176
  [0.6.0]: https://github.com/Freaky/monotime/commits/v0.6.0
105
177
  [0.6.1]: https://github.com/Freaky/monotime/commits/v0.6.1
106
178
  [0.7.0]: https://github.com/Freaky/monotime/commits/v0.7.0
179
+ [0.7.1]: https://github.com/Freaky/monotime/commits/v0.7.0
180
+ [0.8.0]: https://github.com/Freaky/monotime/commits/v0.8.0
181
+ [0.8.1]: https://github.com/Freaky/monotime/commits/v0.8.1
107
182
  [issue #1]: https://github.com/Freaky/monotime/issues/1
183
+ [Ruby #16740]: https://bugs.ruby-lang.org/issues/16740
108
184
  [@celsworth]: https://github.com/celsworth
185
+ [@petergoldstein]: https://github.com/petergoldstein
186
+ [@fig]: https://github.com/fig
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
- [![Gem Version](https://badge.fury.io/rb/monotime.svg)](https://badge.fury.io/rb/monotime)
2
- ![Build Status](https://github.com/Freaky/monotime/actions/workflows/ci.yml/badge.svg)
3
- [![Inline docs](http://inch-ci.org/github/Freaky/monotime.svg?branch=master)](http://inch-ci.org/github/Freaky/monotime)
4
- [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/monotime)
5
1
 
6
2
  # Monotime
7
3
 
8
4
  A sensible interface to Ruby's monotonic clock, inspired by Rust.
9
5
 
6
+ [![Gem Version](https://badge.fury.io/rb/monotime.svg)](https://badge.fury.io/rb/monotime)
7
+ [![Build Status](https://github.com/Freaky/monotime/actions/workflows/ci.yml/badge.svg)](https://github.com/Freaky/monotime/actions)
8
+ [![Inline docs](http://inch-ci.org/github/Freaky/monotime.svg?branch=master)](http://inch-ci.org/github/Freaky/monotime)
9
+ [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/gems/monotime)
10
+
10
11
  ## Installation
11
12
 
12
13
  Add this line to your application's Gemfile:
@@ -23,7 +24,7 @@ Or install it yourself as:
23
24
 
24
25
  $ gem install monotime
25
26
 
26
- `Monotime` is tested on Ruby 2.5&mdash;3.0 and recent JRuby 9.x releases.
27
+ `Monotime` is tested on Ruby 2.7+, TruffleRuby, and JRuby.
27
28
 
28
29
  ## Usage
29
30
 
@@ -106,7 +107,7 @@ Duration.secs(1).sleep # => 1
106
107
 
107
108
  So can `Instant`, taking a `Duration` and sleeping until the given `Duration`
108
109
  past the time the `Instant` was created, if any. This can be useful for
109
- maintaining a precise candence between tasks:
110
+ maintaining a precise cadence between tasks:
110
111
 
111
112
  ```ruby
112
113
  interval = Duration.secs(60)
@@ -159,7 +160,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
159
160
 
160
161
  ## Contributing
161
162
 
162
- Bug reports and pull requests are welcome on GitHub at https://github.com/Freaky/monotime.
163
+ Bug reports and pull requests are welcome on GitHub at <https://github.com/Freaky/monotime>.
163
164
 
164
165
  ## License
165
166
 
@@ -169,14 +170,19 @@ The gem is available as open source under the terms of the [MIT License](https:/
169
170
 
170
171
  ### Core Ruby
171
172
 
172
- For a zero-dependency alternative, see
173
+ For a zero-dependency alternative upon which `monotime` is based, see
173
174
  [`Process.clock_gettime`](https://ruby-doc.org/core-2.6.3/Process.html#method-c-clock_gettime).
174
- `monotime` currently only uses `Process::CLOCK_MONOTONIC`, but others may offer higher precision
175
- depending on platform.
175
+
176
+ `Process::CLOCK_MONOTONIC` is a safe default, but other options may offer better
177
+ behaviour in face of NTP frequency skew or suspend/resume and should be evaluated
178
+ carefully.
176
179
 
177
180
  ### Other Gems
178
181
 
179
182
  [hitimes](https://rubygems.org/gems/hitimes) is a popular and mature alternative
180
183
  which also includes a variety of features for gathering statistics about
181
- measurements, and may offer higher precision on some platforms.
184
+ measurements.
182
185
 
186
+ [concurrent-ruby](https://rubygems.org/gems/concurrent-ruby) includes
187
+ `Concurrent.monotonic_time`, which is at the time of writing a trivial proxy to
188
+ the aforementioned `Process::clock_gettime` with `Process::CLOCK_MONOTONIC`.
@@ -8,16 +8,57 @@ module Monotime
8
8
  # Create a new +Duration+ of a specified number of nanoseconds, zero by
9
9
  # default.
10
10
  #
11
- # Users are strongly advised to use +#from_nanos+ instead.
11
+ # Users are strongly advised to use +Duration.from_nanos+ instead.
12
12
  #
13
13
  # @param nanos [Integer]
14
- # @see #from_nanos
14
+ # @see from_nanos
15
15
  def initialize(nanos = 0)
16
16
  @ns = Integer(nanos)
17
17
  freeze
18
18
  end
19
19
 
20
+ # A static instance for zero durations
21
+ ZERO = allocate.tap { |d| d.__send__(:initialize, 0) }
22
+
23
+ class << self
24
+ # The sleep function used by all +Monotime+ sleep functions.
25
+ #
26
+ # This function must accept a positive +Float+ number of seconds and return
27
+ # the +Float+ time slept.
28
+ #
29
+ # Defaults to +Kernel.method(:sleep)+
30
+ #
31
+ # @overload sleep_function=(function)
32
+ # @param function [#call]
33
+ attr_accessor :sleep_function
34
+
35
+ # Precision for +Duration#to_s+ if not otherwise specified
36
+ #
37
+ # Defaults to 9.
38
+ #
39
+ # @overload default_to_s_precision=(precision)
40
+ # @param precision [Numeric]
41
+ attr_accessor :default_to_s_precision
42
+ end
43
+
44
+ self.sleep_function = Kernel.method(:sleep)
45
+ self.default_to_s_precision = 9
46
+
20
47
  class << self
48
+ # @!visibility private
49
+ def new(nanos = 0)
50
+ return ZERO if nanos.zero?
51
+
52
+ super
53
+ end
54
+
55
+ # Return a zero +Duration+.
56
+ #
57
+ # @return [Duration]
58
+ def zero
59
+ ZERO
60
+ end
61
+
21
62
  # Generate a new +Duration+ measuring the given number of seconds.
22
63
  #
23
64
  # @param secs [Numeric]
@@ -87,7 +128,7 @@ module Monotime
87
128
  # @example
88
129
  # (Duration.from_secs(10) + Duration.from_secs(5)).to_s # => "15s"
89
130
  #
90
- # @param [Duration, #to_nanos]
131
+ # @param other [Duration, #to_nanos]
91
132
  # @return [Duration]
92
133
  def +(other)
93
134
  raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)
@@ -101,7 +142,7 @@ module Monotime
101
142
  # @example
102
143
  # (Duration.from_secs(10) - Duration.from_secs(5)).to_s # => "5s"
103
144
  #
104
- # @param [Duration, #to_nanos]
145
+ # @param other [Duration, #to_nanos]
105
146
  # @return [Duration]
106
147
  def -(other)
107
148
  raise TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)
@@ -114,7 +155,7 @@ module Monotime
114
155
  # @example
115
156
  # (Duration.from_secs(10) / 2).to_s # => "5s"
116
157
  #
117
- # @param [Numeric]
158
+ # @param other [Numeric]
118
159
  # @return [Duration]
119
160
  def /(other)
120
161
  Duration.new(to_nanos / other)
@@ -125,7 +166,7 @@ module Monotime
125
166
  # @example
126
167
  # (Duration.from_secs(10) * 2).to_s # => "20s"
127
168
  #
128
- # @param [Numeric]
169
+ # @param other [Numeric]
129
170
  # @return [Duration]
130
171
  def *(other)
131
172
  Duration.new(to_nanos * other)
@@ -158,7 +199,7 @@ module Monotime
158
199
  # Compare the *value* of this +Duration+ with another, or any +#to_nanos+-coercible
159
200
  # object, or nil if not comparable.
160
201
  #
161
- # @param [Duration, #to_nanos, Object]
202
+ # @param other [Duration, #to_nanos, Object]
162
203
  # @return [-1, 0, 1, nil]
163
204
  def <=>(other)
164
205
  to_nanos <=> other.to_nanos if other.respond_to?(:to_nanos)
@@ -167,7 +208,7 @@ module Monotime
167
208
  # Compare the equality of the *value* of this +Duration+ with another, or
168
209
  # any +#to_nanos+-coercible object, or nil if not comparable.
169
210
  #
170
- # @param [Duration, #to_nanos, Object]
211
+ # @param other [Duration, #to_nanos, Object]
171
212
  # @return [Boolean]
172
213
  def ==(other)
173
214
  other.respond_to?(:to_nanos) && to_nanos == other.to_nanos
@@ -175,7 +216,7 @@ module Monotime
175
216
 
176
217
  # Check equality of the value and type of this +Duration+ with another.
177
218
  #
178
- # @param [Duration, Object]
219
+ # @param other [Duration, Object]
179
220
  # @return [Boolean]
180
221
  def eql?(other)
181
222
  other.is_a?(Duration) && to_nanos == other.to_nanos
@@ -185,7 +226,7 @@ module Monotime
185
226
  #
186
227
  # @return [Integer]
187
228
  def hash
188
- self.class.hash ^ to_nanos.hash
229
+ [self.class, to_nanos].hash
189
230
  end
190
231
 
191
232
  # Return this +Duration+ in seconds.
@@ -255,6 +296,8 @@ module Monotime
255
296
  # Sleep for the duration of this +Duration+. Equivalent to
256
297
  # +Kernel.sleep(duration.to_secs)+.
257
298
  #
299
+ # The sleep function may be overridden globally using +Duration.sleep_function=+
300
+ #
258
301
  # @example
259
302
  # Duration.from_secs(1).sleep # => 1
260
303
  # Duration.from_secs(-1).sleep # => raises NotImplementedError
@@ -262,10 +305,11 @@ module Monotime
262
305
  # @raise [NotImplementedError] negative +Duration+ sleeps are not yet supported.
263
306
  # @return [Integer]
264
307
  # @see Instant#sleep
308
+ # @see sleep_function=
265
309
  def sleep
266
310
  raise NotImplementedError, 'time travel module missing' if negative?
267
311
 
268
- Kernel.sleep(to_secs)
312
+ self.class.sleep_function.call(to_secs)
269
313
  end
270
314
 
271
315
  DIVISORS = [
@@ -280,6 +324,8 @@ module Monotime
280
324
  # Format this +Duration+ into a human-readable string, with a given number
281
325
  # of decimal places.
282
326
  #
327
+ # The default precision may be set globally using +Duration.default_to_s_precision=+
328
+ #
283
329
  # The exact format is subject to change, users with specific requirements
284
330
  # are encouraged to use their own formatting methods.
285
331
  #
@@ -293,7 +339,8 @@ module Monotime
293
339
  #
294
340
  # @param precision [Integer] the maximum number of decimal places
295
341
  # @return [String]
296
- def to_s(precision = 9)
342
+ # @see default_to_s_precision=
343
+ def to_s(precision = self.class.default_to_s_precision)
297
344
  precision = Integer(precision).abs
298
345
  div, unit = DIVISORS.find { |d, _| to_nanos.abs >= d }
299
346
 
@@ -11,13 +11,74 @@ module Monotime
11
11
 
12
12
  include Comparable
13
13
 
14
+ class << self
15
+ # @overload clock_id
16
+ # The +Process.clock_gettime+ clock id used to create +Instant+ instances
17
+ # by the default monotonic function.
18
+ #
19
+ # @return [Numeric]
20
+ #
21
+ # @overload clock_id=(id)
22
+ #
23
+ # Override the default +Process.clock_gettime+ clock id. Some potential
24
+ # choices include but are not limited to:
25
+ #
26
+ # * +Process::CLOCK_MONOTONIC_RAW+
27
+ # * +Process::CLOCK_UPTIME_RAW+
28
+ # * +Process::CLOCK_UPTIME_PRECISE+
29
+ # * +Process::CLOCK_UPTIME_FAST+
30
+ # * +Process::CLOCK_UPTIME+
31
+ # * +Process::CLOCK_MONOTONIC_PRECISE+
32
+ # * +Process::CLOCK_MONOTONIC_FAST+
33
+ # * +Process::CLOCK_MONOTONIC+
34
+ #
35
+ # These are platform-dependant and may vary in resolution, performance,
36
+ # and behaviour from NTP frequency skew and system suspend/resume, and
37
+ # should be selected with care.
38
+ #
39
+ # It is possible to set non-monotonic clock sources here. You probably
40
+ # shouldn't.
41
+ #
42
+ # Defaults to +Process::CLOCK_MONOTONIC+.
43
+ #
44
+ # @param id [Numeric]
45
+ attr_accessor :clock_id
46
+
47
+ # The function used to create +Instant+ instances.
48
+ #
49
+ # This function must return a +Numeric+, monotonic count of nanoseconds
50
+ # since a fixed point in the past.
51
+ #
52
+ # Defaults to +-> { Process.clock_gettime(clock_id, :nanosecond) }+.
53
+ #
54
+ # @overload monotonic_function=(function)
55
+ # @param function [#call]
56
+ attr_accessor :monotonic_function
57
+
58
+ # Return the claimed resolution of the given clock id or the configured
59
+ # +clock_id+, as a +Duration+, or +nil+ if invalid.
60
+ #
61
+ # Note per Ruby issue #16740, the practical usability of this method is
62
+ # dubious and non-portable.
63
+ #
64
+ # @param clock [Numeric] Optional clock id instead of default.
65
+ def clock_getres(clock = clock_id)
66
+ Duration.from_nanos(Process.clock_getres(clock, :nanosecond))
67
+ rescue SystemCallError
68
+ # suppress errors
69
+ end
70
+ end
71
+
72
+ self.monotonic_function = -> { Process.clock_gettime(clock_id, :nanosecond) }
73
+ self.clock_id = Process::CLOCK_MONOTONIC
74
+
14
75
  # Create a new +Instant+ from an optional nanosecond measurement.
15
76
  #
16
77
  # Users should generally *not* pass anything to this function.
17
78
  #
18
79
  # @param nanos [Integer]
19
80
  # @see #now
20
- def initialize(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))
81
+ def initialize(nanos = self.class.monotonic_function.call)
21
82
  @ns = Integer(nanos)
22
83
  freeze
23
84
  end
@@ -112,8 +173,8 @@ module Monotime
112
173
  # Sugar for +#elapsed.to_s+.
113
174
  #
114
175
  # @see Duration#to_s
115
- def to_s(*args)
116
- elapsed.to_s(*args)
176
+ def to_s(...)
177
+ elapsed.to_s(...)
117
178
  end
118
179
 
119
180
  # Add a +Duration+ or +#to_nanos+-coercible object to this +Instant+, returning
@@ -173,7 +234,7 @@ module Monotime
173
234
  #
174
235
  # @return [Integer]
175
236
  def hash
176
- self.class.hash ^ @ns.hash
237
+ [self.class, @ns].hash
177
238
  end
178
239
  end
179
240
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Monotime
4
- # Try to avoid blatting existing VERSION constants when we're included.
5
- MONOTIME_VERSION = '0.7.1'
4
+ # Version of the `monotime` gem
5
+ MONOTIME_VERSION = '0.8.1'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: monotime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Hurst
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-22 00:00:00.000000000 Z
11
+ date: 2023-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  requirements: []
112
- rubygems_version: 3.2.22
112
+ rubygems_version: 3.4.18
113
113
  signing_key:
114
114
  specification_version: 4
115
115
  summary: A sensible interface to the monotonic clock