module Polyphony::FiberControlClassMethods

Class methods for controlling fibers (namely await and select)

Public Instance Methods

await(*fibers) click to toggle source
# File lib/polyphony/extensions/fiber.rb, line 117
def await(*fibers)
  return [] if fibers.empty?

  current_fiber = self.current
  mailbox = current_fiber.monitor_mailbox
  results = {}
  fibers.each do |f|
    results[f] = nil
    if f.dead?
      # fiber already terminated, so queue message
      mailbox << [f, f.result]
    else
      f.monitor(current_fiber)
    end
  end
  exception = nil
  while !fibers.empty?
    (fiber, result) = mailbox.shift
    next unless fibers.include?(fiber)
    fibers.delete(fiber)
    current_fiber.remove_child(fiber) if fiber.parent == current_fiber
    if result.is_a?(Exception)
      exception ||= result
      fibers.each { |f| f.terminate }
    else
      results[fiber] = result
    end
  end
  raise exception if exception
  results.values
end
Also aliased as: join
join(*fibers)
Alias for: await
schedule_priority_oob_fiber(&block) click to toggle source

Creates and schedules with priority an out-of-band fiber that runs the supplied block. If any uncaught exception is raised while the fiber is running, it will bubble up to the main thread's main fiber, which will also be scheduled with priority. This method is mainly used trapping signals (see also the patched `Kernel#trap`)

# File lib/polyphony/extensions/fiber.rb, line 181
def schedule_priority_oob_fiber(&block)
  f = Fiber.new do
    Fiber.current.setup_raw
    block.call
  rescue Exception => e
    Thread.current.schedule_and_wakeup(Thread.main.main_fiber, e)
  end
  Thread.current.schedule_and_wakeup(f, nil)
end
select(*fibers) click to toggle source
# File lib/polyphony/extensions/fiber.rb, line 150
def select(*fibers)
  return nil if fibers.empty?
  
  current_fiber = self.current
  mailbox = current_fiber.monitor_mailbox
  fibers.each do |f|
    if f.dead?
      result = f.result
      result.is_a?(Exception) ? (raise result) : (return [f, result])
    end
  end

  fibers.each { |f| f.monitor(current_fiber) }
  while true
    (fiber, result) = mailbox.shift
    next unless fibers.include?(fiber)
  
    fibers.each { |f| f.unmonitor(current_fiber) }
    if result.is_a?(Exception)
      raise result
    else
      return [fiber, result]
    end
  end
end