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
|
# frozen_string_literal: true
# Released under the MIT License.
# Copyright, 2025, by Samuel Williams.
module Async
# Represents a flexible timeout that can be rescheduled or extended.
# @public Since *Async v2.24*.
class Timeout
# Initialize a new timeout.
def initialize(timers, handle)
@timers = timers
@handle = handle
end
# @returns [Numeric] The time remaining until the timeout occurs, in seconds.
def duration
@handle.time - @timers.now
end
# Update the duration of the timeout.
#
# The duration is relative to the current time, e.g. setting the duration to 5 means the timeout will occur in 5 seconds from now.
#
# @parameter value [Numeric] The new duration to assign to the timeout, in seconds.
def duration=(value)
self.reschedule(@timers.now + value)
end
# Adjust the timeout by the specified duration.
#
# The duration is relative to the timeout time, e.g. adjusting the timeout by 5 increases the current duration by 5 seconds.
#
# @parameter duration [Numeric] The duration to adjust the timeout by, in seconds.
# @returns [Numeric] The new time at which the timeout will occur.
def adjust(duration)
self.reschedule(time + duration)
end
# @returns [Numeric] The time at which the timeout will occur, in seconds since {now}.
def time
@handle.time
end
# Assign a new time to the timeout, rescheduling it if necessary.
#
# @parameter value [Numeric] The new time to assign to the timeout.
# @returns [Numeric] The new time at which the timeout will occur.
def time=(value)
self.reschedule(value)
end
# @returns [Numeric] The current time in the scheduler, relative to the time of this timeout, in seconds.
def now
@timers.now
end
# Cancel the timeout, preventing it from executing.
def cancel!
@handle.cancel!
end
# @returns [Boolean] Whether the timeout has been cancelled.
def cancelled?
@handle.cancelled?
end
# Raised when attempting to reschedule a cancelled timeout.
class CancelledError < RuntimeError
end
# Reschedule the timeout to occur at the specified time.
#
# @parameter time [Numeric] The new time to schedule the timeout for.
# @returns [Numeric] The new time at which the timeout will occur.
private def reschedule(time)
if block = @handle&.block
@handle.cancel!
@handle = @timers.schedule(time, block)
return time
else
raise CancelledError, "Cannot reschedule a cancelled timeout!"
end
end
end
end
|