<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/mongrel/semaphore.rb</filename>
    </added>
    <added>
      <filename>test/test_suite.rb</filename>
    </added>
    <added>
      <filename>test/unit/test_semaphore.rb</filename>
    </added>
    <added>
      <filename>test/unit/test_threading.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -31,6 +31,7 @@ module Mongrel
         ['-l', '--log FILE', &quot;Where to write log messages&quot;, :@log_file, &quot;log/mongrel.log&quot;],
         ['-P', '--pid FILE', &quot;Where to write the PID&quot;, :@pid_file, &quot;log/mongrel.pid&quot;],
         ['-n', '--num-processors INT', &quot;Number of processors active before clients denied&quot;, :@num_processors, 1024],
+        ['-N', '--num-threads INT', &quot;Maximum number of requests to process concurrently&quot;, :@max_concurrent_threads, 1024],
         ['-o', '--timeout TIME', &quot;Time to wait (in seconds) before killing a stalled thread&quot;, :@timeout, 60],
         ['-t', '--throttle TIME', &quot;Time to pause (in hundredths of a second) between accepting clients&quot;, :@throttle, 0],
         ['-m', '--mime PATH', &quot;A YAML file that lists additional MIME types&quot;, :@mime_map, nil],
@@ -181,7 +182,7 @@ module Mongrel
 
     def config_keys
       @config_keys ||=
-        %w(address host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script num_processors timeout throttle user group prefix)
+        %w(address host port cwd log_file pid_file environment docroot mime_map daemon debug includes config_script num_processors timeout throttle user group prefix max_concurrent_threads)
     end
 
     def settings</diff>
      <filename>bin/mongrel_rails</filename>
    </modified>
    <modified>
      <diff>@@ -28,6 +28,7 @@ require 'mongrel/const'
 require 'mongrel/http_request'
 require 'mongrel/header_out'
 require 'mongrel/http_response'
+require 'mongrel/semaphore'
 
 # Mongrel module containing all of the classes (include C extensions) for running
 # a Mongrel web server.  It contains a minimalist HTTP server with just enough
@@ -87,7 +88,8 @@ module Mongrel
     # The throttle parameter is a sleep timeout (in hundredths of a second) that is placed between 
     # socket.accept calls in order to give the server a cheap throttle time.  It defaults to 0 and
     # actually if it is 0 then the sleep is not done at all.
-    def initialize(host, port, num_processors=950, throttle=0, timeout=60)
+    def initialize(host, port, options = {})
+      options = {:num_processors =&gt; 950, :throttle =&gt; 0, :timeout =&gt; 60}.merge(options)
       
       tries = 0
       @socket = TCPServer.new(host, port) 
@@ -96,9 +98,10 @@ module Mongrel
       @host = host
       @port = port
       @workers = ThreadGroup.new
-      @throttle = throttle / 100.0
-      @num_processors = num_processors
-      @timeout = timeout
+      @throttle = options[:throttle] / 100.0
+      @num_processors = options[:num_processors]
+      @timeout = options[:timeout]
+      @max_concurrent_threads = options[:max_concurrent_threads] || @num_processors
     end
 
     # Does the majority of the IO processing.  It has been written in Ruby using
@@ -257,6 +260,7 @@ module Mongrel
     # Runs the thing.  It returns the thread used so you can &quot;join&quot; it.  You can also
     # access the HttpServer::acceptor attribute to get the thread later.
     def run
+      semaphore = Semaphore.new(@max_concurrent_threads)
       BasicSocket.do_not_reverse_lookup=true
 
       configure_socket_options
@@ -282,7 +286,7 @@ module Mongrel
                 client.close rescue nil
                 reap_dead_workers(&quot;max processors&quot;)
               else
-                thread = Thread.new(client) {|c| process_client(c) }
+                thread = Thread.new(client) {|c| semaphore.synchronize { process_client(c) } }
                 thread[:started_on] = Time.now
                 @workers.add(thread)
   </diff>
      <filename>lib/mongrel.rb</filename>
    </modified>
    <modified>
      <diff>@@ -132,11 +132,8 @@ module Mongrel
     def listener(options={},&amp;block)
       raise &quot;Cannot call listener inside another listener block.&quot; if (@listener or @listener_name)
       ops = resolve_defaults(options)
-      ops[:num_processors] ||= 950
-      ops[:throttle] ||= 0
-      ops[:timeout] ||= 60
 
-      @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops[:num_processors].to_i, ops[:throttle].to_i, ops[:timeout].to_i)
+      @listener = Mongrel::HttpServer.new(ops[:host], ops[:port].to_i, ops)
       @listener_name = &quot;#{ops[:host]}:#{ops[:port]}&quot;
       @listeners[@listener_name] = @listener
 </diff>
      <filename>lib/mongrel/configurator.rb</filename>
    </modified>
    <modified>
      <diff>@@ -67,15 +67,10 @@ module Mongrel
         else
           begin
             cgi = Mongrel::CGIWrapper.new(request, response)
-            cgi.handler = self
-            # We don't want the output to be really final until we're out of the lock
+            # We don't want the output to be really final until the dispatch returns a response.
             cgi.default_really_final = false
 
-            @guard.synchronize {
-              @active_request_path = request.params[Mongrel::Const::PATH_INFO] 
-              Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
-              @active_request_path = nil
-            }
+            Dispatcher.dispatch(cgi, ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS, response.body)
 
             # This finalizes the output using the proper HttpResponse way
             cgi.out(&quot;text/html&quot;,true) {&quot;&quot;}</diff>
      <filename>lib/mongrel/rails.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,7 +26,7 @@ class WebServerTest &lt; Test::Unit::TestCase
     
     redirect_test_io do
       # We set num_processors=1 so that we can test the reaping code
-      @server = HttpServer.new(&quot;127.0.0.1&quot;, @port, num_processors=1)
+      @server = HttpServer.new(&quot;127.0.0.1&quot;, @port, :num_processors =&gt; 1)
     end
     
     @tester = TestHandler.new</diff>
      <filename>test/unit/test_ws.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>64d8d94bea8dcf1ac3a9a2782e846b39a8dc5c63</id>
    </parent>
  </parents>
  <author>
    <name>Pivotal  Labs</name>
    <email>pivotal@cumberland.flood.pivotallabs.com</email>
  </author>
  <url>http://github.com/pivotal/mongrel/commit/5915b8af83b1d191ecabde76da56932cc08c107a</url>
  <id>5915b8af83b1d191ecabde76da56932cc08c107a</id>
  <committed-date>2008-08-27T17:00:02-07:00</committed-date>
  <authored-date>2008-08-27T17:00:02-07:00</authored-date>
  <message>pt/am - Added option to throttle number of concurrent threads processing requests.</message>
  <tree>631019fc008e259d40647780924e8adb3d5cfaa1</tree>
  <committer>
    <name>Pivotal  Labs</name>
    <email>pivotal@cumberland.flood.pivotallabs.com</email>
  </committer>
</commit>
