Class: EventCore::FiberSource

Inherits:
Source
  • Object
show all
Defined in:
lib/event_core.rb

Overview

Source for Ruby Fibers run on the mainloop. When a fiber yields it returns control to the mainloop. It supports async sub-tasks in sync-style programming by yielding Procs. See MainLoop.add_fiber for details.

Instance Method Summary collapse

Methods inherited from Source

#closed?, #event_factory, #notify_trigger, #ready?, #select_io, #select_type, #timeout, #trigger

Constructor Details

#initialize(loop, proc = nil) ⇒ FiberSource

Returns a new instance of FiberSource.



203
204
205
206
207
208
209
210
211
# File 'lib/event_core.rb', line 203

def initialize(loop, proc=nil)
  super()
  raise "First arg must be a MainLoop: #{loop}" unless loop.is_a? MainLoop
  raise "Second arg must be a Proc: #{proc.class}" unless (proc.is_a? Proc or proc.nil?)

  @loop = loop

  create_fiber(proc) if proc
end

Instance Method Details

#close!Object



224
225
226
227
# File 'lib/event_core.rb', line 224

def close!
  super
  @fiber = nil
end

#consume_event_data!Object



218
219
220
221
222
# File 'lib/event_core.rb', line 218

def consume_event_data!
  event_data = super
  @ready = true
  event_data
end

#create_fiber(proc) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/event_core.rb', line 229

def create_fiber(proc)
  raise "Arg must be a Proc: #{proc.class}" unless proc.is_a? Proc
  raise "Fiber already created for this source" if @fiber

  @fiber = Fiber.new { proc.call }

  @ready = true

  trigger { |async_task_data|
    task = @fiber.resume(async_task_data)

    # If yielding, maybe spawn an async sub-task?
    if @fiber.alive?
      if task.is_a? Proc
        raise "Fibers on the main loop must take exactly 1 argument. Proc takes #{task.arity}" unless task.arity == 1
        @ready = false # don't fire again until task is done
        @loop.add_once {
          fiber_task = FiberTask.new(self)
          task.call(fiber_task)
        }
      elsif task.nil?
        # all good, just yielding until next loop iteration
      else
        raise "Fibers that yield must return nil or a Proc: #{task.class}"
      end
    end

    next @fiber.alive?
  }

  nil
end

#ready!(event_data = nil) ⇒ Object



213
214
215
216
# File 'lib/event_core.rb', line 213

def ready!(event_data=nil)
  super(event_data)
  @loop.send_wakeup
end