|
2 | 2 | require 'active_support/core_ext/object/blank'
|
3 | 3 | require 'active_support/core_ext/object/try'
|
4 | 4 | require 'active_support/core_ext/kernel/singleton_class'
|
| 5 | +require 'thread' |
5 | 6 |
|
6 | 7 | module ActionView
|
7 | 8 | # = Action View Template
|
@@ -123,6 +124,7 @@ def initialize(source, identifier, handler, details)
|
123 | 124 | @virtual_path = details[:virtual_path]
|
124 | 125 | @updated_at = details[:updated_at] || Time.now
|
125 | 126 | @formats = Array.wrap(format).map { |f| f.is_a?(Mime::Type) ? f.ref : f }
|
| 127 | + @compile_mutex = Mutex.new |
126 | 128 | end
|
127 | 129 |
|
128 | 130 | # Returns if the underlying handler supports streaming. If so,
|
@@ -224,18 +226,28 @@ def encode!
|
224 | 226 | def compile!(view) #:nodoc:
|
225 | 227 | return if @compiled
|
226 | 228 |
|
227 |
| - if view.is_a?(ActionView::CompiledTemplates) |
228 |
| - mod = ActionView::CompiledTemplates |
229 |
| - else |
230 |
| - mod = view.singleton_class |
231 |
| - end |
| 229 | + # Templates can be used concurrently in threaded environments |
| 230 | + # so compilation and any instance variable modification must |
| 231 | + # be synchronized |
| 232 | + @compile_mutex.synchronize do |
| 233 | + # Any thread holding this lock will be compiling the template needed |
| 234 | + # by the threads waiting. So re-check the @compiled flag to avoid |
| 235 | + # re-compilation |
| 236 | + return if @compiled |
| 237 | + |
| 238 | + if view.is_a?(ActionView::CompiledTemplates) |
| 239 | + mod = ActionView::CompiledTemplates |
| 240 | + else |
| 241 | + mod = view.singleton_class |
| 242 | + end |
232 | 243 |
|
233 |
| - compile(view, mod) |
| 244 | + compile(view, mod) |
234 | 245 |
|
235 |
| - # Just discard the source if we have a virtual path. This |
236 |
| - # means we can get the template back. |
237 |
| - @source = nil if @virtual_path |
238 |
| - @compiled = true |
| 246 | + # Just discard the source if we have a virtual path. This |
| 247 | + # means we can get the template back. |
| 248 | + @source = nil if @virtual_path |
| 249 | + @compiled = true |
| 250 | + end |
239 | 251 | end
|
240 | 252 |
|
241 | 253 | # Among other things, this method is responsible for properly setting
|
|
0 commit comments