tests: "wc -c" portability for *BSDs
[rainbows.git] / lib / rainbows / thread_spawn.rb
blobb30468865a9b1fdb64747261c7d229be0ac7bea0
1 # -*- encoding: binary -*-
2 require 'thread'
4 # Spawns a new thread for every client connection we accept().  This
5 # model is recommended for platforms like Ruby (MRI) 1.8 where spawning
6 # new threads is inexpensive, but still seems to work well enough with
7 # good native threading implementations such as NPTL under Linux on
8 # Ruby (MRI/YARV) 1.9
10 # This model should provide a high level of compatibility with all Ruby
11 # implementations, and most libraries and applications.  Applications
12 # running under this model should be thread-safe but not necessarily
13 # reentrant.
15 # If you're using green threads (MRI 1.8) and need to perform DNS lookups,
16 # consider using the "resolv-replace" library which replaces parts of the
17 # core Socket package with concurrent DNS lookup capabilities.
19 module Rainbows::ThreadSpawn
20   include Rainbows::Base
21   include Rainbows::WorkerYield
23   def accept_loop(klass) #:nodoc:
24     lock = Mutex.new
25     limit = worker_connections
26     nr = 0
27     LISTENERS.each do |l|
28       klass.new do
29         begin
30           if lock.synchronize { nr >= limit }
31             worker_yield
32           elsif client = l.kgio_accept
33             klass.new(client) do |c|
34               begin
35                 lock.synchronize { nr += 1 }
36                 c.process_loop
37               ensure
38                 lock.synchronize { nr -= 1 }
39               end
40             end
41           end
42         rescue => e
43           Rainbows::Error.listen_loop(e)
44         end while Rainbows.alive
45       end
46     end
47     sleep 1 while Rainbows.tick || lock.synchronize { nr > 0 }
48   end
50   def worker_loop(worker) #:nodoc:
51     init_worker_process(worker)
52     accept_loop(Thread)
53   end
54 end