class LightIO::Core::Beam
Beam
is light-weight executor, provide thread-like interface
@Example:
#- initialize with block b = Beam.new{puts "hello"} b.join #output: hello b = Beam.new(1,2,3){|one, two, three| puts [one, two, three].join(",") } b.join #output: 1,2,3 #- use join wait beam done b = Beam.new(){LightIO.sleep 3} b.join b.alive? # false
Attributes
Public Class Methods
Create a new beam
Beam
is light-weight executor, provide thread-like interface
Beam.new
(“hello”){|hello| puts hello }
@param [Array] args pass arguments to Beam
block @param [Proc] blk block to execute @return [Beam]
# File lib/lightio/core/beam.rb, line 47 def initialize(*args, &blk) raise LightIO::Error, "must be called with a block" unless blk super() { begin @value = yield(*args) rescue Exception => e @error = e end # mark as dead dead # transfer back to parent(caller fiber) after schedule parent.transfer } # schedule beam in ioloop ioloop.add_callback {transfer} @alive = true end
Schedule beams
normally beam should be auto scheduled, use this method to manually trigger a schedule
@return [nil]
# File lib/lightio/core/beam.rb, line 147 def pass running = IOloop.current.running schedule = LightIO::Watchers::Schedule.new IOloop.current.wait(schedule) # make sure ioloop run once pass unless running end
Public Instance Methods
# File lib/lightio/core/beam.rb, line 65 def alive? super && @alive end
Block and wait beam dead
@param [Numeric] limit wait limit seconds if limit > 0, return nil if beam still alive, else return beam self @return [Beam, nil]
# File lib/lightio/core/beam.rb, line 83 def join(limit=nil) # try directly get result if !alive? || limit.nil? || limit <= 0 # call value to raise error value return self end # return to current beam if beam done within time limit origin_parent = parent self.parent = Beam.current # set a transfer back timer timer = LightIO::Watchers::Timer.new(limit) timer.set_callback do if alive? caller_beam = parent # resume to origin parent self.parent = origin_parent caller_beam.transfer end end ioloop.add_timer(timer) ioloop.transfer if alive? nil else check_and_raise_error self end end
Kill beam
@return [Beam]
# File lib/lightio/core/beam.rb, line 118 def kill dead parent.transfer if self == Beam.current self end
Fiber not provide raise method, so we have to simulate one @param [BeamError] error currently only support raise BeamError
# File lib/lightio/core/beam.rb, line 126 def raise(error, message=nil, backtrace=nil) unless error.is_a?(BeamError) message ||= error.respond_to?(:message) ? error.message : nil backtrace ||= error.respond_to?(:backtrace) ? error.backtrace : nil super(error, message, backtrace) end self.parent = error.parent if error.parent if Beam.current == self raise(error.error, message, backtrace) else @error ||= error end end
block and wait beam return a value
# File lib/lightio/core/beam.rb, line 70 def value if alive? self.parent = Beam.current ioloop.transfer end check_and_raise_error @value end
Private Instance Methods
# File lib/lightio/core/beam.rb, line 176 def check_and_raise_error raise @error if @error end
mark beam as dead
# File lib/lightio/core/beam.rb, line 159 def dead @alive = false on_dead.call(self) if on_dead end
get parent/ioloop to transfer back
# File lib/lightio/core/beam.rb, line 172 def parent @parent || ioloop end