/
monotonic_time.rb
91 lines (82 loc) · 2.64 KB
/
monotonic_time.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
require 'concurrent/synchronization'
module Concurrent
class_definition = Class.new(Synchronization::LockableObject) do
def initialize
@last_time = Time.now.to_f
super()
end
if defined?(Process::CLOCK_MONOTONIC)
# @!visibility private
def get_time(unit)
Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
end
elsif Concurrent.on_jruby?
# @!visibility private
TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
private_constant :TIME_UNITS
TIME_UNITS.merge!(
second: 1_000_000_000,
millisecond: 1_000_000,
microsecond: 1_000,
nanosecond: 1,
float_second: 1_000_000_000.0,
float_millisecond: 1_000_000.0,
float_microsecond: 1_000.0,
)
# @!visibility private
def get_time(unit)
java.lang.System.nanoTime() / TIME_UNITS[unit]
end
else
# @!visibility private
TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
private_constant :TIME_UNITS
TIME_UNITS.merge!(
second: [nil, true],
millisecond: [1_000, true],
microsecond: [1_000_000, true],
nanosecond: [1_000_000_000, true],
float_second: [nil, false],
float_millisecond: [1_000.0, false],
float_microsecond: [1_000_000.0, false],
)
# @!visibility private
def get_time(unit)
synchronize do
now = Time.now.to_f
if @last_time < now
@last_time = now
else # clock has moved back in time
@last_time += 0.000_001
end
scale, to_int = TIME_UNITS[unit]
now *= scale if scale
now = now.to_i if to_int
now
end
end
end
end
# Clock that cannot be set and represents monotonic time since
# some unspecified starting point.
#
# @!visibility private
GLOBAL_MONOTONIC_CLOCK = class_definition.new
private_constant :GLOBAL_MONOTONIC_CLOCK
# @!macro monotonic_get_time
#
# Returns the current time a tracked by the application monotonic clock.
#
# @param [Symbol] unit the time unit to be returned, can be either
# :float_second, :float_millisecond, :float_microsecond, :second,
# :millisecond, :microsecond, or :nanosecond default to :float_second.
#
# @return [Float] The current monotonic time since some unspecified
# starting point
#
# @!macro monotonic_clock_warning
def monotonic_time(unit = :float_second)
GLOBAL_MONOTONIC_CLOCK.get_time(unit)
end
module_function :monotonic_time
end