# Author:: Mohammad A. Ali (mailto:oldmoe@gmail.com)
# Copyright:: Copyright (c) 2008 eSpace, Inc.
# License:: Distributes under the same terms as Ruby
$:.unshift File.expand_path(File.dirname(__FILE__))
# Thanks to Aman Gupta for writing the Ruby 1.8 Fiber simulator
unless defined? Fiber
require 'thread'
require 'singleton'
class FiberError < StandardError; end
class Fiber
def initialize
raise ArgumentError, 'new Fiber requires a block' unless block_given?
@yield = Queue.new
@resume = Queue.new
@thread = Thread.new{ @yield.push [ *yield(*@resume.pop) ] }
@thread.abort_on_exception = true
@thread[:fiber] = self
end
attr_reader :thread
def resume *args
raise FiberError, 'dead fiber called' unless @thread.alive?
@resume.push(args)
result = @yield.pop
result.size > 1 ? result : result.first
end
def yield *args
@yield.push(args)
result = @resume.pop
result.size > 1 ? result : result.first
end
def self.yield *args
raise FiberError, "can't yield from root fiber" unless fiber = Thread.current[:fiber]
fiber.yield(*args)
end
def self.current
Thread.current[:fiber] or raise FiberError, 'not inside a fiber'
end
def inspect
"#<#{self.class}:0x#{self.object_id.to_s(16)}>"
end
end
class RootFiber < Fiber
include Singleton
def initialize
end
def resume *args
raise FiberError, "can't resume root fiber"
end
def yield *args
raise FiberError, "can't yield from root fiber"
end
end
#attach the root fiber to the main thread
Thread.main[:fiber] = RootFiber.instance
else
require 'fiber'
end
require 'never_block/extensions/fiber_extensions'
require 'never_block/pool/fiber_pool'
require 'never_block/pool/fibered_connection_pool'
module NeverBlock
# Checks if we should be working in a non-blocking mode
def self.neverblocking?
Fiber.respond_to?(:current) && Fiber.current[:neverblock]
end
def self.event_loop_available?
defined?(EM) && EM.reactor_running?
end
# The given block will run its queries either in blocking or non-blocking
# mode based on the first parameter
def self.neverblock(nb = true, &block)
status = Fiber.current[:neverblock]
Fiber.current[:neverblock] = nb
block.call
Fiber.current[:neverblock] = status
end
# Exception to be thrown for all neverblock internal errors
class NBError < StandardError
end
end
puts "Using Neverblock"
NB = NeverBlock