Class: Monotime::Instant

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/monotime/instant.rb

Overview

A measurement from the operating system’s monotonic clock, with up to nanosecond precision.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)) ⇒ Instant

Create a new Instant from an optional nanosecond measurement.

Users should generally not pass anything to this function.

Parameters:

  • nanos (Integer) (defaults to: Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))

See Also:

  • #now


20
21
22
23
# File 'lib/monotime/instant.rb', line 20

def initialize(nanos = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond))
  @ns = Integer(nanos)
  freeze
end

Class Method Details

.nowInstant

An alias to new, and generally preferred over it.

Returns:



28
29
30
# File 'lib/monotime/instant.rb', line 28

def self.now
  new
end

Instance Method Details

#+(other) ⇒ Instant

Add a Duration or #to_nanos-coercible object to this Instant, returning a new Instant.

Examples:

(Instant.now + Duration.from_secs(1)).to_s # => "-999.983976ms"

Parameters:

Returns:



127
128
129
130
131
# File 'lib/monotime/instant.rb', line 127

def +(other)
  return TypeError, 'Not one of: [Duration, #to_nanos]' unless other.respond_to?(:to_nanos)

  Instant.new(@ns + other.to_nanos)
end

#-(other) ⇒ Duration, Instant

Subtract another Instant to generate a Duration between the two, or a Duration or #to_nanos-coercible object, to generate an Instant offset by it.

Examples:

(Instant.now - Duration.from_secs(1)).to_s # => "1.000016597s"
(Instant.now - Instant.now).to_s           # => "-3.87μs"

Parameters:

Returns:



143
144
145
146
147
148
149
150
151
# File 'lib/monotime/instant.rb', line 143

def -(other)
  if other.is_a?(Instant)
    Duration.new(@ns - other.ns)
  elsif other.respond_to?(:to_nanos)
    Instant.new(@ns - other.to_nanos)
  else
    raise TypeError, 'Not one of: [Instant, Duration, #to_nanos]'
  end
end

#<=>(other) ⇒ -1, ...

Determine if the given Instant is before, equal to or after this one. nil if not passed an Instant.

Returns:

  • (-1, 0, 1, nil)


157
158
159
# File 'lib/monotime/instant.rb', line 157

def <=>(other)
  @ns <=> other.ns if other.is_a?(Instant)
end

#==(other) ⇒ Boolean Also known as: eql?

Determine if other‘s value equals that of this Instant. Use eql? if type checks are desired for future compatibility.

Returns:

  • (Boolean)

See Also:



166
167
168
# File 'lib/monotime/instant.rb', line 166

def ==(other)
  other.is_a?(Instant) && @ns == other.ns
end

#duration_since(earlier) ⇒ Duration

Return a Duration between this Instant and another.

Parameters:

Returns:

Raises:

  • (TypeError)


36
37
38
39
40
# File 'lib/monotime/instant.rb', line 36

def duration_since(earlier)
  raise TypeError, 'Not an Instant' unless earlier.is_a?(Instant)

  earlier - self
end

#elapsedDuration

Return a Duration since this Instant and now.

Returns:



45
46
47
# File 'lib/monotime/instant.rb', line 45

def elapsed
  duration_since(self.class.now)
end

#hashInteger

Generate a hash for this type and value.

Returns:

  • (Integer)


175
176
177
# File 'lib/monotime/instant.rb', line 175

def hash
  self.class.hash ^ @ns.hash
end

#in_future?Boolean Also known as: future?

Return whether this Instant is in the future.

Returns:

  • (Boolean)


61
62
63
# File 'lib/monotime/instant.rb', line 61

def in_future?
  elapsed.negative?
end

#in_past?Boolean Also known as: past?

Return whether this Instant is in the past.

Returns:

  • (Boolean)


52
53
54
# File 'lib/monotime/instant.rb', line 52

def in_past?
  elapsed.positive?
end

#sleep(duration = nil) ⇒ Duration

Sleep until this Instant, plus an optional Duration, returning a Duration that’s either positive if any time was slept, or negative if sleeping would require time travel.

Examples:

Sleeps for a second

start = Instant.now
sleep 0.5 # do stuff for half a second
start.sleep(Duration.from_secs(1)).to_s # => "490.088706ms" (slept)
start.sleep(Duration.from_secs(1)).to_s # => "-12.963502ms" (did not sleep)

Also sleeps for a second.

one_second_in_the_future = Instant.now + Duration.from_secs(1)
one_second_in_the_future.sleep.to_s     # => "985.592712ms" (slept)
one_second_in_the_future.sleep.to_s     # => "-4.71217ms" (did not sleep)

Parameters:

  • duration (nil, Duration, #to_nanos) (defaults to: nil)

Returns:

  • (Duration)

    the slept duration, if #positive?, else the overshot time



84
85
86
87
88
# File 'lib/monotime/instant.rb', line 84

def sleep(duration = nil)
  remaining = duration ? duration - elapsed : -elapsed

  remaining.tap { |rem| rem.sleep if rem.positive? }
end

#sleep_millis(millis) ⇒ Duration

Sleep for the given number of milliseconds past this Instant, if any.

Equivalent to #sleep(Duration.from_millis(millis))

Parameters:

  • millis (Numeric)

    number of milliseconds to sleep past this Instant

Returns:

  • (Duration)

    the slept duration, if #positive?, else the overshot time

See Also:



108
109
110
# File 'lib/monotime/instant.rb', line 108

def sleep_millis(millis)
  sleep(Duration.from_millis(millis))
end

#sleep_secs(secs) ⇒ Duration

Sleep for the given number of seconds past this Instant, if any.

Equivalent to #sleep(Duration.from_secs(secs))

Parameters:

  • secs (Numeric)

    number of seconds to sleep past this Instant

Returns:

  • (Duration)

    the slept duration, if #positive?, else the overshot time

See Also:



97
98
99
# File 'lib/monotime/instant.rb', line 97

def sleep_secs(secs)
  sleep(Duration.from_secs(secs))
end

#to_s(*args) ⇒ Object

Sugar for #elapsed.to_s.

See Also:



115
116
117
# File 'lib/monotime/instant.rb', line 115

def to_s(*args)
  elapsed.to_s(*args)
end