%h1 Rainbows! at a glance
%p
  Confused by all the options we give you?  So are we!  Here's some tables
  to help keep your head straight.  Remember, engineering is all about
  trade-offs.
%h2 core features and compatibility
%br
%table.comp
  %tr.comp_header
    %th.mod module
    %th.tee rack.input streaming
    %th.r18 Ruby 1.8
    %th.r19 Ruby 1.9
    %th.rbx Rubinius
    %th.slow slow clients
  %tr.comp_base
    %td.mod Unicorn/Base
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow No
  %tr.comp_row
    %td.mod Revactor
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod ThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod Coolio
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod EventMachine
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.tee No
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod FiberSpawn
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod FiberPool
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_base
    %td.mod ActorSpawn
    %td.tee Yes
    %td.r18 Not yet
    %td.r19 No
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_base
    %td.mod NeverBlock
    %td.tee No
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.tee No
    %td.r18 Yes
    %td.r19 No
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.tee Yes
    %td.r18 No
    %td.r19 Yes
    %td.rbx No
    %td.slow Yes
  %tr.comp_row
    %td.mod WriterThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow no
  %tr.comp_row
    %td.mod WriterThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow no
  %tr.comp_row
    %td.mod Epoll
    %td.tee no
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpoll
    %td.tee no
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpollThreadSpawn
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
  %tr.comp_row
    %td.mod XEpollThreadPool
    %td.tee Yes
    %td.r18 Yes
    %td.r19 Yes
    %td.rbx Yes
    %td.slow Yes
%ul
  %li
    Cool.io should also work with Rubinius (though we haven't had time to test).
  %li
    CoolioThread* and CoolioThread* requires Ruby 1.9 reasonable performance
  %li
    rack.input streaming is what makes
    %a(href="http://upr.bogomips.org/") upload progress,
    and BOSH possible
  %li
    rack.input streaming is NOT compatible with current versions of nginx
    or any proxy that fully buffers request bodies before proxying.
    Keep in mind request body buffering in nginx is a good thing in all
    other cases where rack.input streaming is not needed.

%h2 application requirements
%br
%table.comp
  %tr.comp_header
    %th.mod module
    %th.slowio slow I/O (backend, not client)
    %th.thr thread safety
    %th.reent single thread reentrant
  %tr.comp_base
    %td.mod Unicorn/Base
    %td.slowio avoid
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod Revactor
    %td.slowio
      %a(href="http://coolio.github.com/")Coolio,
      %a(href="http://revactor.org/")Revactor,
      %b
        not
      %a(href="Rainbows/Fiber/IO.html")Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod ThreadPool
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod Coolio
    %td.slowio
      %a(href="http://coolio.github.com/") Coolio
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod EventMachine
    %td.slowio
      %a(href="http://rubyeventmachine.com") EventMachine
    %td.thr No
    %td.reent No
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.slowio
      thread-safe Ruby,
      %a(href="http://coolio.github.com/") Coolio
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod FiberSpawn
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod FiberPool
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_base
    %td.mod ActorSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent Yes
  %tr.comp_base
    %td.mod NeverBlock
    %td.slowio
      %a(href="http://www.espace.com.eg/neverblock") NeverBlock,
      %a(href="http://rubyeventmachine.com") EventMachine
    %td.thr No
    %td.reent Yes
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.slowio
      thread-safe Ruby,
      %a(href="http://coolio.github.com/") Coolio
    %td.thr Yes
    %td.reent No
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.slowio
      %a(href="Rainbows/Fiber/IO.html") Rainbows::Fiber::IO
    %td.thr No
    %td.reent Yes
  %tr.comp_base
    %td.mod WriterThreadPool
    %td.slowio avoid
    %td.thr Maybe
    %td.reent Maybe
  %tr.comp_base
    %td.mod WriterThreadSpawn
    %td.slowio avoid
    %td.thr Maybe
    %td.reent Maybe
  %tr.comp_base
    %td.mod Epoll
    %td.slowio No
    %td.thr No
    %td.reent No
  %tr.comp_base
    %td.mod XEpoll
    %td.slowio No
    %td.thr No
    %td.reent No
  %tr.comp_base
    %td.mod XEpollThreadSpawn
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
  %tr.comp_base
    %td.mod XEpollThreadPool
    %td.slowio thread-safe Ruby
    %td.thr Yes
    %td.reent No
%ul
  %li
    Requirements for single thread reentrancy are loose in that there is
    no risk of race conditions and potentially mutually exclusive to
    thread-safety.  In the case where a Fiber yields while holding a
    resource and another Fiber attempting to acquire it may raise
    an error or worse, deadlock the entire process.
  %li
    Slow I/O means anything that can block/stall on sockets including
    3rd-party APIs (OpenID providers included) or slow database queries.
    Properly run Memcached (within the same LAN) is fast and not a blocker.
    Slow I/O on POSIX filesystems only includes a few operations, namely
    on UNIX domain sockets and named pipes.  Nearly all other operations
    on POSIX filesystems can be considered "fast", or at least
    uninterruptible.
  %li
    WriterThread{Pool,Spawn} will require thread safety if your response
    body is dynamically generated during the body#each call.

%h2 middlewares and frameworks
%br

%table.comp
  %tr.comp_header
    %th.mod model
    %th.devfd
      %a(href="Rainbows/DevFdResponse.html") DevFdResponse
    %th.app_pool
      %a(href="Rainbows/AppPool.html") AppPool
    %th.lock
      %a(href="http://rdoc.info/gems/rack/Rack/Lock") Rack::Lock
    %th.async async
  %tr.comp_row
    %td.mod Unicorn/Base
    %td.devfd no-op
    %td.app_pool no-op
    %td.lock no-op
    %td.async lots of RAM :P
  %tr.comp_row
    %td.mod Revactor
    %td.devfd no-op
    %td.app_pool Yes
    %td.lock No!
    %td.async Revactor itself
  %tr.comp_row
    %td.mod ThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod Coolio
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod ThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod EventMachine
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async async_sinatra, Cramp, rack-fiber_pool
  %tr.comp_row
    %td.mod CoolioThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Dumb
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod FiberSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod FiberPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod ActorSpawn
    %td.devfd no-op
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod NeverBlock
    %td.devfd Yes
    %td.app_pool Yes*
    %td.lock Yes*
    %td.async NeverBlock, async_sinatra
  %tr.comp_row
    %td.mod CoolioThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Dumb
    %td.async Coolio, thread-safe Ruby
  %tr.comp_row
    %td.mod CoolioFiberSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock No!
    %td.async Coolio, Rainbows::Fiber::IO, Rainbows.sleep
  %tr.comp_row
    %td.mod WriterThreadPool
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async thread-safe Ruby in response body only
  %tr.comp_row
    %td.mod WriterThreadSpawn
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async thread-safe Ruby in response body only
  %tr.comp_row
    %td.mod Epoll
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod XEpoll
    %td.devfd Yes
    %td.app_pool no-op
    %td.lock no-op
    %td.async DevFdResponse
  %tr.comp_row
    %td.mod XEpollThreadPool
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
  %tr.comp_row
    %td.mod XEpollThreadSpawn
    %td.devfd Yes
    %td.app_pool Yes
    %td.lock Yes
    %td.async thread-safe Ruby
%ul
  %li
    "No!" means it's fundamentally incompatible, use an
    %a(href="Rainbows/AppPool.html") AppPool
    %b :size
    of one instead.
  %li
    NeverBlock also supports a :pool_size option which is one less
    layer of complexity than using AppPool.
  %li
    NeverBlock can neuter the Mutex class so Rack::Lock effectively
    becomes a no-op with:
    %br
    %code require "never_block/frameworks/rails"
    (before Rails is loaded)
  %li
    Everything that's DevFdResponse-compatible can use it for passing
    async responses through
