Sha256: bb0c7cba38a51a52c3a4c42fd864509adaa198b48204e8fdc9ce585b99571e67

Contents?: true

Size: 1.36 KB

Versions: 1

Compression:

Stored size: 1.36 KB

Contents

require 'fiber'
require 'eventmachine'

module EventMachine::SyncDefer
  module_function
  def defer *funcs, &block
    fiber = Fiber.current
    funcs << block if block_given?
    if    funcs.empty?
      return
    elsif funcs.size == 1
      defer_one(fiber, funcs.first)
    else
      defer_multi(fiber, funcs)
    end
    result, exception = Fiber.yield
    if exception
      raise exception
    else
      result
    end
  end

  def defer_one fiber, func
    exception = nil
    EventMachine.defer(lambda{
                         begin
                           func.call
                         rescue Exception => e
                           exception = e
                         end
                       },
                       lambda{ |result| fiber.resume(result, exception)})
  end

  def defer_multi fiber, funcs
    results, exception = {}, nil
    funcs.each.with_index do |func, index|
      EventMachine.defer(
        lambda{
          begin
            func.call
          rescue Exception => e
            exception = e
          end
        },
        lambda{ |result|
          if exception
            fiber.resume(nil, exception) if fiber.alive?
          else
            results[index] = result
            fiber.resume(results.sort.map(&:last), nil) if
              results.size == funcs.size && fiber.alive?
          end
        })
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
sync-defer-0.9.7 lib/eventmachine/sync-defer.rb