lib/nanoc/base/memoization.rb in nanoc-4.1.6 vs lib/nanoc/base/memoization.rb in nanoc-4.2.0b1
- old
+ new
@@ -1,12 +1,22 @@
+require 'weakref'
+
module Nanoc::Int
# Adds support for memoizing functions.
#
# @api private
#
# @since 3.2.0
module Memoization
+ class Wrapper
+ attr_reader :value
+
+ def initialize(value)
+ @value = value
+ end
+ end
+
# Memoizes the method with the given name. The modified method will cache
# the results of the original method, so that calling a method twice with
# the same arguments will short-circuit and return the cached results
# immediately.
#
@@ -37,27 +47,24 @@
#
# @param [Symbol, String] method_name The name of the method to memoize
#
# @return [void]
def memoize(method_name)
- # Alias
original_method_name = '__nonmemoized_' + method_name.to_s
alias_method original_method_name, method_name
- # Redefine
define_method(method_name) do |*args|
- # Get cache
@__memoization_cache ||= {}
@__memoization_cache[method_name] ||= {}
+ method_cache = @__memoization_cache[method_name]
- # Recalculate if necessary
- unless @__memoization_cache[method_name].key?(args)
- result = send(original_method_name, *args)
- @__memoization_cache[method_name][args] = result
+ if method_cache.key?(args) && method_cache[args].weakref_alive?
+ method_cache[args].value
+ else
+ send(original_method_name, *args).tap do |r|
+ method_cache[args] = WeakRef.new(Wrapper.new(r))
+ end
end
-
- # Done
- @__memoization_cache[method_name][args]
end
end
end
end