class Async::Reactor
def run_once(timeout = nil)
-
(Boolean)
- whether there is more work to do.
Parameters:
-
timeout
(Float | nil
) -- the maximum timeout, or if nil, indefinite.
def run_once(timeout = nil) # Console.logger.debug(self) {"@ready = #{@ready} @running = #{@running}"} if @ready.any? # running used to correctly answer on `finished?`, and to reuse Array object. @running, @ready = @ready, @running @running.each do |fiber| fiber.resume if fiber.alive? end @running.clear end if @unblocked.any? unblocked = Array.new @guard.synchronize do unblocked, @unblocked = @unblocked, unblocked end while fiber = unblocked.pop fiber.resume if fiber.alive? end end if @ready.empty? interval = @timers.wait_interval else # if there are tasks ready to execute, don't sleep: interval = 0 end # If we are finished, we stop the task tree and exit: if self.finished? return false end # If there is no interval to wait (thus no timers), and no tasks, we could be done: if interval.nil? # Allow the user to specify a maximum interval if we would otherwise be sleeping indefinitely: interval = timeout elsif interval < 0 # We have timers ready to fire, don't sleep in the selctor: interval = 0 elsif timeout and interval > timeout interval = timeout end # Console.logger.info(self) {"Selecting with #{@children&.size} children with interval = #{interval ? interval.round(2) : 'infinite'}..."} if monitors = @selector.select(interval) monitors.each do |monitor| monitor.value.resume end end @timers.fire # We check and clear the interrupted flag here: if @interrupted @guard.synchronize do @interrupted = false end return false end # The reactor still has work to do: return true end