Skip to content

Commit 132dfae

Browse files
committed
Better documentation of monotonic clocks.
1 parent f45e952 commit 132dfae

File tree

5 files changed

+58
-14
lines changed

5 files changed

+58
-14
lines changed

lib/concurrent.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,24 @@
2929
require 'concurrent/timer_task'
3030
require 'concurrent/tvar'
3131

32+
# @!macro [new] monotonic_clock_warning
33+
#
34+
# @note Time calculations one all platforms and languages are sensitive to
35+
# changes to the system clock. To alleviate the potential problems
36+
# associated with changing the system clock while an application is running,
37+
# most modern operating systems provide a monotonic clock that operates
38+
# independently of the system clock. A monotonic clock cannot be used to
39+
# determine human-friendly clock times. A monotonic clock is used exclusively
40+
# for calculating time intervals. Not all Ruby platforms provide access to an
41+
# operating system monotonic clock. On these platforms a pure-Ruby monotonic
42+
# clock will be used as a fallback. An operating system monotonic clock is both
43+
# faster and more reliable than the pure-Ruby implementation. The pure-Ruby
44+
# implementation should be fast and reliable enough for most non-realtime
45+
# operations. At this time the common Ruby platforms that provide access to an
46+
# operating system monotonic clock are MRI 2.1 and above and JRuby (all versions).
47+
#
48+
# @see http://linux.die.net/man/3/clock_gettime Linux clock_gettime(3)
49+
3250
# Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,
3351
# F#, C#, Java, and classic concurrency patterns.
3452
#

lib/concurrent/atomic/condition.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ def initialize
4343
# @param [Mutex] mutex the locked mutex guarding the wait
4444
# @param [Object] timeout nil means no timeout
4545
# @return [Result]
46+
#
47+
# @!macro monotonic_clock_warning
4648
def wait(mutex, timeout = nil)
4749
start_time = Concurrent.monotonic_time
4850
@condition.wait(mutex, timeout)

lib/concurrent/utility/monotonic_time.rb

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
module Concurrent
22

3+
# Clock that cannot be set and represents monotonic time since
4+
# some unspecified starting point.
5+
# @!visibility private
36
GLOBAL_MONOTONIC_CLOCK = Class.new {
47

58
if defined?(Process::CLOCK_MONOTONIC)
6-
def get_time(other = 0.0)
7-
Process.clock_gettime(Process::CLOCK_MONOTONIC) - other.to_f
9+
# @!visibility private
10+
def get_time(since = 0.0)
11+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - since.to_f
812
end
913
elsif RUBY_PLATFORM == 'java'
10-
def get_time(other = 0.0)
11-
(java.lang.System.nanoTime() / 1_000_000_000.0) - other.to_f
14+
# @!visibility private
15+
def get_time(since = 0.0)
16+
(java.lang.System.nanoTime() / 1_000_000_000.0) - since.to_f
1217
end
1318
else
1419

@@ -21,7 +26,8 @@ def initialize
2126
@last_time = Time.now.to_f
2227
end
2328

24-
def get_time(other = 0.0)
29+
# @!visibility private
30+
def get_time(since = 0.0)
2531
@mutex.synchronize {
2632
@correction ||= 0 # compensating any back time shifts
2733
now = Time.now.to_f
@@ -32,13 +38,26 @@ def get_time(other = 0.0)
3238
@correction += @last_time - corrected_now + 0.000_001
3339
@last_time = @correction + now
3440
end
35-
} - other.to_f
41+
} - since.to_f
3642
end
3743
end
3844
}.new
3945

40-
def monotonic_time(other = 0.0)
41-
GLOBAL_MONOTONIC_CLOCK.get_time(other)
46+
# @!macro [attach] monotonic_get_time
47+
#
48+
# Returns the current time a tracked by the application monotonic clock.
49+
# When no `since` time is given the return value will bet he current time.
50+
# When an `since` value is given the return value will be the monotonic time
51+
# interval which has been passed since the `since` time.
52+
#
53+
# @param [Float] since the monotonic time from which to calculate
54+
# the time interval
55+
# @return [Float] The current monotonic time when `since` not given else
56+
# the elapsed monotonic time between `since` and the current time
57+
#
58+
# @!macro monotonic_clock_warning
59+
def monotonic_time(since = 0.0)
60+
GLOBAL_MONOTONIC_CLOCK.get_time(since)
4261
end
4362
module_function :monotonic_time
4463
end
@@ -76,8 +95,8 @@ def get_time_native
7695
Process.clock_gettime(Process::CLOCK_MONOTONIC)
7796
end
7897

79-
def get_interval_native(other)
80-
Process.clock_gettime(Process::CLOCK_MONOTONIC) - other.to_f
98+
def get_interval_native(since)
99+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - since.to_f
81100
end
82101

83102
def get_time_ruby
@@ -94,8 +113,8 @@ def get_time_ruby
94113
end
95114
end
96115

97-
def get_interval_ruby(other)
98-
get_time_ruby - other.to_f
116+
def get_interval_ruby(since)
117+
get_time_ruby - since.to_f
99118
end
100119
end
101120

lib/concurrent/utility/timeout.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
module Concurrent
77

88
# Wait the given number of seconds for the block operation to complete.
9+
# Intended to be a simpler and more reliable replacement to the Ruby
10+
# standard library `Timeout::timeout` method.
911
#
1012
# @param [Integer] seconds The number of seconds to wait
1113
#
@@ -14,8 +16,9 @@ module Concurrent
1416
# @raise [Concurrent::TimeoutError] when the block operation does not complete
1517
# in the allotted number of seconds.
1618
#
17-
# @note This method is intended to be a simpler and more reliable replacement
18-
# to the Ruby standard library `Timeout::timeout` method.
19+
# @see http://ruby-doc.org/stdlib-2.2.0/libdoc/timeout/rdoc/Timeout.html Ruby Timeout::timeout
20+
#
21+
# @!macro monotonic_clock_warning
1922
def timeout(seconds)
2023

2124
thread = Thread.new do

lib/concurrent/utility/timer.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ module Concurrent
1010
# @yield the task to execute
1111
#
1212
# @return [Boolean] true
13+
#
14+
# @!macro monotonic_clock_warning
1315
def timer(seconds, *args, &block)
1416
raise ArgumentError.new('no block given') unless block_given?
1517
raise ArgumentError.new('interval must be greater than or equal to zero') if seconds < 0

0 commit comments

Comments
 (0)