diff options
Diffstat (limited to 'activesupport')
-rw-r--r-- | activesupport/lib/active_support/memoizable.rb | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb index 4ffb5d9520..8e9abeaf91 100644 --- a/activesupport/lib/active_support/memoizable.rb +++ b/activesupport/lib/active_support/memoizable.rb @@ -1,4 +1,42 @@ module ActiveSupport + class ConcurrentHash + def initialize(hash = {}) + @backup_cache = hash.dup + @frozen_cache = hash.dup.freeze + @mutex = Mutex.new + end + + def []=(k,v) + @mutex.synchronize { @backup_cache[k] = v } + @frozen_cache = @backup_cache.dup.freeze + end + + def [](k) + if @frozen_cache.key?(k) + @frozen_cache[k] + else + @mutex.synchronize { @backup_cache[k] } + end + end + + def empty? + @backup_cache.empty? + end + end + + module SafelyMemoizable + def safely_memoize(*symbols) + symbols.each do |symbol| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{symbol}(*args) + memoized = @_memoized_#{symbol} || ::ActiveSupport::ConcurrentHash.new + memoized[args] ||= memoized_#{symbol}(*args) + end + RUBY + end + end + end + module Memoizable def self.memoized_ivar_for(symbol) "@_memoized_#{symbol.to_s.sub(/\?\Z/, '_query').sub(/!\Z/, '_bang')}".to_sym |