espace / neverblock forked from oldmoe/neverblock

A collection of high level non-blocking IO libraries

This URL has Read+Write access

neverblock / lib / never_block.rb
505d63e5 » humanzz 2008-08-17 more documentation 1 # Author:: Mohammad A. Ali (mailto:oldmoe@gmail.com)
2 # Copyright:: Copyright (c) 2008 eSpace, Inc.
3 # License:: Distributes under the same terms as Ruby
4
8ea633a3 » espace 2008-08-13 adjusting requires 5 $:.unshift File.expand_path(File.dirname(__FILE__))
6
050ce0b5 » oldmoe 2008-10-28 Credits for Aman Gupta for ... 7 # Thanks to Aman Gupta for writing the Ruby 1.8 Fiber simulator
c412799c » humanzz 2008-09-01 better support for ruby 1.8.x 8 unless defined? Fiber
9 require 'thread'
10 require 'singleton'
8c9b5f18 » oldmoe 2008-08-31 initial support for Ruby 1.8.x 11 class FiberError < StandardError; end
12 class Fiber
13 def initialize
14 raise ArgumentError, 'new Fiber requires a block' unless block_given?
15
16 @yield = Queue.new
17 @resume = Queue.new
c412799c » humanzz 2008-09-01 better support for ruby 1.8.x 18
8c9b5f18 » oldmoe 2008-08-31 initial support for Ruby 1.8.x 19 @thread = Thread.new{ @yield.push [ *yield(*@resume.pop) ] }
20 @thread.abort_on_exception = true
21 @thread[:fiber] = self
22 end
23 attr_reader :thread
24
25 def resume *args
26 raise FiberError, 'dead fiber called' unless @thread.alive?
27 @resume.push(args)
28 result = @yield.pop
29 result.size > 1 ? result : result.first
30 end
31
32 def yield *args
33 @yield.push(args)
34 result = @resume.pop
35 result.size > 1 ? result : result.first
36 end
37
38 def self.yield *args
39 raise FiberError, "can't yield from root fiber" unless fiber = Thread.current[:fiber]
40 fiber.yield(*args)
41 end
42
43 def self.current
44 Thread.current[:fiber] or raise FiberError, 'not inside a fiber'
45 end
46
47 def inspect
48 "#<#{self.class}:0x#{self.object_id.to_s(16)}>"
49 end
c412799c » humanzz 2008-09-01 better support for ruby 1.8.x 50 end
51
52 class RootFiber < Fiber
53 include Singleton
54 def initialize
55 end
56
57 def resume *args
58 raise FiberError, "can't resume root fiber"
59 end
60
61 def yield *args
62 raise FiberError, "can't yield from root fiber"
63 end
64 end
65
66 #attach the root fiber to the main thread
67 Thread.main[:fiber] = RootFiber.instance
3890c345 » oldmoe 2008-09-02 better Ruby 1.8 support 68 else
69 require 'fiber'
8c9b5f18 » oldmoe 2008-08-31 initial support for Ruby 1.8.x 70 end
71
8ea633a3 » espace 2008-08-13 adjusting requires 72 require 'never_block/extensions/fiber_extensions'
73 require 'never_block/pool/fiber_pool'
74 require 'never_block/pool/fibered_connection_pool'
75
76 module NeverBlock
a413092f » humanzz 2008-10-23 better mysql support for ha... 77
78 # Checks if we should be working in a non-blocking mode
79 def self.neverblocking?
80 Fiber.respond_to?(:current) && Fiber.current[:neverblock]
81 end
82
83 def self.event_loop_available?
84 defined?(EM) && EM.reactor_running?
85 end
86
87 # The given block will run its queries either in blocking or non-blocking
88 # mode based on the first parameter
0c8155ad » humanzz 2008-09-03 better rails support 89 def self.neverblock(nb = true, &block)
90 status = Fiber.current[:neverblock]
91 Fiber.current[:neverblock] = nb
92 block.call
93 Fiber.current[:neverblock] = status
94 end
bfbd3084 » humanzz 2008-10-27 refactor, refactor... 95
96 # Exception to be thrown for all neverblock internal errors
97 class NBError < StandardError
98 end
99
8ea633a3 » espace 2008-08-13 adjusting requires 100 end
09c1320a » modsaid 2009-02-11 adding message 101 puts "Using Neverblock"
8c9b5f18 » oldmoe 2008-08-31 initial support for Ruby 1.8.x 102 NB = NeverBlock