about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--lib/rainbows.rb1
-rw-r--r--lib/rainbows/app_pool.rb2
-rw-r--r--lib/rainbows/fiber.rb6
-rw-r--r--lib/rainbows/http_server.rb2
-rw-r--r--lib/rainbows/never_block.rb69
-rw-r--r--t/GNUmakefile4
-rw-r--r--t/simple-http_NeverBlock.ru11
-rwxr-xr-xt/t0300-async_sinatra.sh2
-rwxr-xr-xt/t9000-rack-app-pool.sh2
10 files changed, 92 insertions, 9 deletions
diff --git a/TODO b/TODO
index abcaed8..483bd6a 100644
--- a/TODO
+++ b/TODO
@@ -11,8 +11,6 @@ care about.
 
 * {Packet,Rev,EventMachine}+Fibers
 
-* Neverblock
-
 * {Packet,Rev}ThreadPool
 
 * Rev + callcc - current Rev model with callcc (should work with MBARI)
diff --git a/lib/rainbows.rb b/lib/rainbows.rb
index f2f7af5..c8f77c0 100644
--- a/lib/rainbows.rb
+++ b/lib/rainbows.rb
@@ -82,6 +82,7 @@ module Rainbows
     :FiberSpawn => 50,
     :FiberPool => 50,
     :ActorSpawn => 50,
+    :NeverBlock => 50,
   }.each do |model, _|
     u = model.to_s.gsub(/([a-z0-9])([A-Z0-9])/) { "#{$1}_#{$2.downcase!}" }
     autoload model, "rainbows/#{u.downcase!}"
diff --git a/lib/rainbows/app_pool.rb b/lib/rainbows/app_pool.rb
index 5c85e0a..036fe9c 100644
--- a/lib/rainbows/app_pool.rb
+++ b/lib/rainbows/app_pool.rb
@@ -91,7 +91,7 @@ module Rainbows
       # concurrency models
       self.re ||= begin
         case env["rainbows.model"]
-        when :FiberSpawn, :FiberPool, :Revactor
+        when :FiberSpawn, :FiberPool, :Revactor, :NeverBlock
           self.pool = Rainbows::Fiber::Queue.new(pool)
         end
         true
diff --git a/lib/rainbows/fiber.rb b/lib/rainbows/fiber.rb
index c30bd7a..ec0cee3 100644
--- a/lib/rainbows/fiber.rb
+++ b/lib/rainbows/fiber.rb
@@ -1,5 +1,9 @@
 # -*- encoding: binary -*-
-require 'fiber'
+begin
+  require 'fiber'
+rescue LoadError
+  defined?(NeverBlock) or raise
+end
 
 module Rainbows
 
diff --git a/lib/rainbows/http_server.rb b/lib/rainbows/http_server.rb
index b528942..8b9f220 100644
--- a/lib/rainbows/http_server.rb
+++ b/lib/rainbows/http_server.rb
@@ -63,7 +63,7 @@ module Rainbows
       Const::RACK_DEFAULTS['rainbows.model'] = @use = model.to_sym
       Const::RACK_DEFAULTS['rack.multithread'] = !!(/Thread/ =~ model.to_s)
       case @use
-      when :Rev, :EventMachine
+      when :Rev, :EventMachine, :NeverBlock
         Const::RACK_DEFAULTS['rainbows.autochunk'] = true
       end
     end
diff --git a/lib/rainbows/never_block.rb b/lib/rainbows/never_block.rb
new file mode 100644
index 0000000..0933c73
--- /dev/null
+++ b/lib/rainbows/never_block.rb
@@ -0,0 +1,69 @@
+# -*- encoding: binary -*-
+
+module Rainbows
+
+  # {NeverBlock}[www.espace.com.eg/neverblock/] library that combines
+  # the EventMachine library with Ruby Fibers.  This includes use of
+  # Thread-based Fibers under Ruby 1.8.  It currently does NOT support
+  # a streaming "rack.input" but is compatible with everything else
+  # EventMachine supports.
+  #
+  # In your Rainbows! config block, you may specify a Fiber pool size
+  # to limit your application concurrency (without using Rainbows::AppPool)
+  #
+  #   Rainbows! do
+  #     use :NeverBlock, :pool_size => 50
+  #     worker_connections 100
+  #   end
+  #
+  module NeverBlock
+
+    DEFAULTS = {
+      :pool_size => 20, # same default size used by NB
+      :backend => :EventMachine, # NeverBlock doesn't support Rev yet
+    }
+
+    # same pool size NB core itself uses
+    def self.setup
+      DEFAULTS.each { |k,v| O[k] ||= v }
+      Integer === O[:pool_size] && O[:pool_size] > 0 or
+        raise ArgumentError, "pool_size must a be an Integer > 0"
+      mod = Rainbows.const_get(O[:backend])
+      require "never_block" # require EM first since we need a higher version
+      G.server.extend(mod)
+      G.server.extend(Core)
+    end
+
+    module Client
+
+      def self.setup
+        const_set(:POOL, ::NB::Pool::FiberPool.new(O[:pool_size]))
+        Rainbows.const_get(O[:backend]).const_get(:Client).module_eval do
+          include Rainbows::NeverBlock::Client
+          alias _app_call app_call
+          undef_method :app_call
+          alias app_call nb_app_call
+        end
+      end
+
+      def nb_app_call
+        POOL.spawn do
+          begin
+            _app_call
+          rescue => e
+            handle_error(e)
+          end
+        end
+      end
+    end
+
+    module Core
+      def init_worker_process(worker)
+        super
+        Client.setup
+        logger.info "NeverBlock/#{O[:backend]} pool_size=#{O[:pool_size]}"
+      end
+    end
+
+  end
+end
diff --git a/t/GNUmakefile b/t/GNUmakefile
index 52f59df..32893ce 100644
--- a/t/GNUmakefile
+++ b/t/GNUmakefile
@@ -22,7 +22,7 @@ else
 endif
 export RUBYLIB RUBY_VERSION
 
-models = ThreadPool ThreadSpawn Rev EventMachine
+models = ThreadPool ThreadSpawn Rev EventMachine NeverBlock
 rp := )
 ONENINE := $(shell case $(RUBY_VERSION) in 1.9.*$(rp) echo true;;esac)
 ifeq ($(ONENINE),true)
@@ -30,7 +30,7 @@ ifeq ($(ONENINE),true)
   models += FiberSpawn
   models += FiberPool
 
-  # technically this works under 1.8, too, it's just slow
+  # technically this works under 1.8, but wait until rev 0.3.2
   models += RevThreadSpawn
 endif
 all_models := $(models) Base
diff --git a/t/simple-http_NeverBlock.ru b/t/simple-http_NeverBlock.ru
new file mode 100644
index 0000000..31ee561
--- /dev/null
+++ b/t/simple-http_NeverBlock.ru
@@ -0,0 +1,11 @@
+use Rack::ContentLength
+use Rack::ContentType
+run lambda { |env|
+  if env['rack.multithread'] == false &&
+    EM.reactor_running? &&
+    env['rainbows.model'] == :NeverBlock
+    [ 200, {}, [ Thread.current.inspect << "\n" ] ]
+  else
+    raise env.inspect
+  end
+}
diff --git a/t/t0300-async_sinatra.sh b/t/t0300-async_sinatra.sh
index 3cf729c..a623916 100755
--- a/t/t0300-async_sinatra.sh
+++ b/t/t0300-async_sinatra.sh
@@ -5,7 +5,7 @@
 n=10
 CONFIG_RU=async_sinatra.ru
 case $model in
-EventMachine) ;;
+NeverBlock|EventMachine) ;;
 *)
         t_info "skipping $T since it's not compatible with $model"
         exit 0
diff --git a/t/t9000-rack-app-pool.sh b/t/t9000-rack-app-pool.sh
index 544532b..821b6ec 100755
--- a/t/t9000-rack-app-pool.sh
+++ b/t/t9000-rack-app-pool.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 . ./test-lib.sh
 case $model in
-*Thread*|*Fiber*|Revactor) ;;
+*Thread*|*Fiber*|Revactor|NeverBlock) ;;
 *)
         t_info "skipping $T since it's not compatible with $model"
         exit 0