Permalink
Browse files

threads can wait on responses to be committed

  • Loading branch information...
tenderlove committed Jul 27, 2012
1 parent f4d818d commit acb6848468bc4ec035201b23af9affeb8279711f
@@ -226,6 +226,7 @@ def recycle!
@block = nil
@length = 0
@body = []
+ @committed = false
@charset = @content_type = nil
@request = @template = nil
end
@@ -2,6 +2,7 @@
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/class/attribute_accessors'
+require 'monitor'
module ActionDispatch # :nodoc:
# Represents an HTTP response generated by a controller action. Use it to
@@ -62,12 +63,17 @@ class Response
include Rack::Response::Helpers
include ActionDispatch::Http::Cache::Response
+ include MonitorMixin
def initialize(status = 200, header = {}, body = [])
+ super()
+
self.body, self.header, self.status = body, header, status
@sending_file = false
- @blank = false
+ @blank = false
+ @cv = new_cond

This comment has been minimized.

Show comment Hide comment
@josevalim

josevalim Aug 1, 2012

Contributor

Doesn't this mean we are creating a new_cond for all responses? Is it cheap enough or it would be better if we started it only when needed?

@josevalim

josevalim Aug 1, 2012

Contributor

Doesn't this mean we are creating a new_cond for all responses? Is it cheap enough or it would be better if we started it only when needed?

This comment has been minimized.

Show comment Hide comment
@tenderlove

tenderlove Aug 1, 2012

Owner

Ya it means we get a new_cond. I think it's cheap enough, it's basically just a mutex. I think we should wait to see if it's a problem before optimizing.

@tenderlove

tenderlove Aug 1, 2012

Owner

Ya it means we get a new_cond. I think it's cheap enough, it's basically just a mutex. I think we should wait to see if it's a problem before optimizing.

+ @committed = false
if content_type = self[CONTENT_TYPE]
type, charset = content_type.split(/;\s*charset=/)
@@ -80,6 +86,23 @@ def initialize(status = 200, header = {}, body = [])
yield self if block_given?
end
+ def await_commit
+ synchronize do
+ @cv.wait_until { @committed }
+ end
+ end
+
+ def commit!
+ synchronize do
+ @committed = true
+ @cv.broadcast
+ end
+ end
+
+ def committed?
+ synchronize { @committed }
+ end
+
def status=(status)
@status = Rack::Utils.status_code(status)
end
@@ -5,6 +5,15 @@ def setup
@response = ActionDispatch::Response.new
end
+ def test_can_wait_until_commit
+ t = Thread.new {
+ assert @response.await_commit
+ }
+ @response.commit!
+ assert @response.committed?
+ t.join
+ end
+
def test_response_body_encoding
body = ["hello".encode('utf-8')]
response = ActionDispatch::Response.new 200, {}, body

0 comments on commit acb6848

Please sign in to comment.