class IO::Event::Timers

An efficient sorted set of timers.

def after(offset, &block)

@yields {|now| ...} When the timer fires.
@parameter offset [#to_f] The time offset from the current time at which the block should be called.

Schedule a block to be called after a specific time offset, relative to the current time as returned by {#now}.
def after(offset, &block)
	schedule(self.now + offset.to_f, block)
end

def fire(now = self.now)

@parameter now [Float] The current time.

Fire all timers that are ready to fire.
def fire(now = self.now)
	# Flush scheduled timers into the heap:
	flush!
	
	# Get the earliest timer:
	while handle = @heap.peek
		if handle.cancelled?
			@heap.pop
		elsif handle.time <= now
			# Remove the earliest timer from the heap:
			@heap.pop
			
			# Call the block:
			handle.call(now)
		else
			break
		end
	end
end

def flush!

This is a small optimization which assumes that most timers (timeouts) will be cancelled.

Flush all scheduled timers into the heap.
def flush!
dle = @scheduled.pop
sh(handle) unless handle.cancelled?

def initialize

Initialize the timers.
def initialize
	@heap = PriorityHeap.new
	@scheduled = []
end

def now

@returns [Float] The current time.
def now
	::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
end

def schedule(time, block)

@parameter block [Proc] The block to call.
@parameter time [Float] The time at which the block should be called, relative to {#now}.

Schedule a block to be called at a specific time in the future.
def schedule(time, block)
	handle = Handle.new(time, block)
	
	@scheduled << handle
	
	return handle
end

def size

@returns [Integer] The number of timers in the heap.
def size
	flush!
	
	return @heap.size
end

def wait_interval(now = self.now)

@returns [Float | Nil] The time interval until the next timer fires, if any.
@parameter now [Float] The current time.

Compute the time interval until the next timer fires.
def wait_interval(now = self.now)
	flush!
	
	while handle = @heap.peek
		if handle.cancelled?
			@heap.pop
		else
			return handle.time - now
		end
	end
end