Skip to content

Commit 0473caf

Browse files
committed
Concurrent.monotonic_time accept an optional unit parameter
This is a direct transposition of MRI's `clock_gettime` unit option.
1 parent 0cca522 commit 0473caf

File tree

2 files changed

+68
-7
lines changed

2 files changed

+68
-7
lines changed

lib/concurrent-ruby/concurrent/utility/monotonic_time.rb

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,52 @@ def initialize
1010

1111
if defined?(Process::CLOCK_MONOTONIC)
1212
# @!visibility private
13-
def get_time
14-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
13+
def get_time(unit)
14+
Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
1515
end
1616
elsif Concurrent.on_jruby?
1717
# @!visibility private
18-
def get_time
19-
java.lang.System.nanoTime() / 1_000_000_000.0
18+
self::TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
19+
self::TIME_UNITS.merge!(
20+
second: 1_000_000_000,
21+
millisecond: 1_000_000,
22+
microsecond: 1_000,
23+
nanosecond: 1,
24+
float_second: 1_000_000_000.0,
25+
float_millisecond: 1_000_000.0,
26+
float_microsecond: 1_000.0,
27+
)
28+
29+
# @!visibility private
30+
def get_time(unit)
31+
java.lang.System.nanoTime() / TIME_UNITS[unit]
2032
end
2133
else
34+
# @!visibility private
35+
self::TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
36+
self::TIME_UNITS.merge!(
37+
second: [nil, true],
38+
millisecond: [1_000, true],
39+
microsecond: [1_000_000, true],
40+
nanosecond: [1_000_000_000, true],
41+
float_second: [nil, false],
42+
float_millisecond: [1_000.0, false],
43+
float_microsecond: [1_000_000.0, false],
44+
)
2245

2346
# @!visibility private
24-
def get_time
47+
def get_time(unit)
2548
synchronize do
2649
now = Time.now.to_f
2750
if @last_time < now
2851
@last_time = now
2952
else # clock has moved back in time
3053
@last_time += 0.000_001
3154
end
55+
scale, to_int = TIME_UNITS[unit]
56+
now *= scale if scale
57+
now = now.to_i if to_int
58+
now
3259
end
3360
end
3461

@@ -46,12 +73,16 @@ def get_time
4673
#
4774
# Returns the current time a tracked by the application monotonic clock.
4875
#
76+
# @param [Symbol] unit the time unit to be returned, can be either
77+
# :float_second, :float_millisecond, :float_microsecond, :second,
78+
# :millisecond, :microsecond, or :nanosecond default to :float_second.
79+
#
4980
# @return [Float] The current monotonic time since some unspecified
5081
# starting point
5182
#
5283
# @!macro monotonic_clock_warning
53-
def monotonic_time
54-
GLOBAL_MONOTONIC_CLOCK.get_time
84+
def monotonic_time(unit = :float_second)
85+
GLOBAL_MONOTONIC_CLOCK.get_time(unit)
5586
end
5687

5788
module_function :monotonic_time
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module Concurrent
2+
3+
RSpec.describe :monotonic_time do
4+
context 'behavior' do
5+
6+
it 'returns seconds as float' do
7+
expect(Concurrent.monotonic_time).to be_a(Float)
8+
end
9+
10+
%i(float_second float_millisecond float_microsecond).each do |unit|
11+
it "returns a Float when unit = #{unit.inspect}" do
12+
expect(Concurrent.monotonic_time(unit)).to be_a(Float)
13+
end
14+
end
15+
16+
%i(second millisecond microsecond nanosecond).each do |unit|
17+
it "returns an Integer when unit = #{unit.inspect}" do
18+
expect(Concurrent.monotonic_time(unit)).to be_an(Integer)
19+
end
20+
end
21+
22+
it 'raises ArgumentError on unknown units' do
23+
expect {
24+
Concurrent.monotonic_time(:foo)
25+
}.to raise_error(ArgumentError)
26+
end
27+
28+
end
29+
end
30+
end

0 commit comments

Comments
 (0)