File: timeout.rb

package info (click to toggle)
ruby-async 2.36.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 400 kB
  • sloc: ruby: 1,938; makefile: 4
file content (88 lines) | stat: -rw-r--r-- 2,526 bytes parent folder | download
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