public
Fork of oldmoe/neverblock
Description: A collection of high level non-blocking IO libraries
Homepage:
Clone URL: git://github.com/espace/neverblock.git
neverblock / lib / never_block.rb
100644 103 lines (82 sloc) 2.568 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# 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