diff options
author | José Valim <jose.valim@gmail.com> | 2012-05-20 14:01:52 -0700 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2012-05-20 14:01:52 -0700 |
commit | fe9731ee674b8d7d7e06f81441fceb0499734493 (patch) | |
tree | fc6f6212c9259da97e5b5aa2c862ae46cdc168bc | |
parent | 6ef9fda1a39f45e2d18aba4881f60a19589a2c77 (diff) | |
parent | 565c1b0a0772ac6cf91c77e9285806f7b028614c (diff) | |
download | rails-fe9731ee674b8d7d7e06f81441fceb0499734493.tar.gz rails-fe9731ee674b8d7d7e06f81441fceb0499734493.tar.bz2 rails-fe9731ee674b8d7d7e06f81441fceb0499734493.zip |
Merge pull request #6407 from pinetops/565c1b0a0772ac6cf91c77e9285806f7b028614c
Template concurrency fixes
-rw-r--r-- | actionpack/lib/action_view/template.rb | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb index eac6287b0b..e67e52cc76 100644 --- a/actionpack/lib/action_view/template.rb +++ b/actionpack/lib/action_view/template.rb @@ -2,6 +2,7 @@ require 'active_support/core_ext/array/wrap' require 'active_support/core_ext/object/blank' require 'active_support/core_ext/object/try' require 'active_support/core_ext/kernel/singleton_class' +require 'thread' module ActionView # = Action View Template @@ -123,6 +124,7 @@ module ActionView @virtual_path = details[:virtual_path] @updated_at = details[:updated_at] || Time.now @formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f } + @compile_mutex = Mutex.new end # Returns if the underlying handler supports streaming. If so, @@ -224,18 +226,28 @@ module ActionView def compile!(view) #:nodoc: return if @compiled - if view.is_a?(ActionView::CompiledTemplates) - mod = ActionView::CompiledTemplates - else - mod = view.singleton_class - end + # Templates can be used concurrently in threaded environments + # so compilation and any instance variable modification must + # be synchronized + @compile_mutex.synchronize do + # Any thread holding this lock will be compiling the template needed + # by the threads waiting. So re-check the @compiled flag to avoid + # re-compilation + return if @compiled + + if view.is_a?(ActionView::CompiledTemplates) + mod = ActionView::CompiledTemplates + else + mod = view.singleton_class + end - compile(view, mod) + compile(view, mod) - # Just discard the source if we have a virtual path. This - # means we can get the template back. - @source = nil if @virtual_path - @compiled = true + # Just discard the source if we have a virtual path. This + # means we can get the template back. + @source = nil if @virtual_path + @compiled = true + end end # Among other things, this method is responsible for properly setting |