Class: LightIO::Core::Beam

Inherits:
LightFiber show all
Defined in:
lib/lightio/core/beam.rb

Overview

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

Defined Under Namespace

Classes: BeamError

Constant Summary

Constants inherited from LightFiber

LightFiber::ROOT_FIBER

Instance Attribute Summary collapse

Attributes inherited from LightFiber

#ioloop, #on_transfer

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from LightFiber

is_root?, #transfer

Constructor Details

#initialize(*args, &blk) ⇒ Beam

Create a new beam

Beam is light-weight executor, provide thread-like interface

Beam.new(“hello”){|hello| puts hello }

Parameters:

  • args (Array)

    pass arguments to Beam block

  • blk (Proc)

    block to execute

Raises:



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# 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

Instance Attribute Details

#errorObject (readonly)

Returns the value of attribute error.



35
36
37
# File 'lib/lightio/core/beam.rb', line 35

def error
  @error
end

#on_deadObject

Returns the value of attribute on_dead.



36
37
38
# File 'lib/lightio/core/beam.rb', line 36

def on_dead
  @on_dead
end

Class Method Details

.passnil

Schedule beams

normally beam should be auto scheduled, use this method to manually trigger a schedule

Returns:

  • (nil)


147
148
149
150
151
152
153
# 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

Instance Method Details

#alive?Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/lightio/core/beam.rb', line 65

def alive?
  super && @alive
end

#join(limit = nil) ⇒ Beam?

Block and wait beam dead

Parameters:

  • limit (Numeric) (defaults to: nil)

    wait limit seconds if limit > 0, return nil if beam still alive, else return beam self

Returns:



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# 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

#killBeam

Kill beam

Returns:



118
119
120
121
122
# File 'lib/lightio/core/beam.rb', line 118

def kill
  dead
  parent.transfer if self == Beam.current
  self
end

#raise(error, message = nil, backtrace = nil) ⇒ Object

Fiber not provide raise method, so we have to simulate one

Parameters:

  • error (BeamError)

    currently only support raise BeamError



126
127
128
129
130
131
132
133
134
135
136
137
138
# 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

#valueObject

block and wait beam return a value



70
71
72
73
74
75
76
77
# 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