module ExpiringMemoize
Constants
- VERSION
Public Class Methods
gettime()
click to toggle source
@nodoc
# File lib/expiring_memoize.rb, line 40 def self.gettime Process.clock_gettime Process::CLOCK_MONOTONIC_COARSE end
Public Instance Methods
memoize(name, ttl: Float::INFINITY)
click to toggle source
Memoize a nullary method. @param name [Symbol] method to memoize @option ttl [Number] time to live of the value, in seconds
# File lib/expiring_memoize.rb, line 7 def memoize name, ttl: Float::INFINITY original = instance_method name raise ArgumentError, 'only nullary methods supported' unless original.arity.zero? define_method name do data = ((@_expiring_memoize_data ||= {})[name] ||= {}) loop do # no need to synchronize here -- worst case, # we return a value fresher than expected. # (plus, global interpreter lock in MRI makes it safe regardless) unless (ts = data[:timestamp]) && (ExpiringMemoize.gettime - ts) < ttl # value is stale, race to fetch mutex ||= (data[:mutex] ||= Mutex.new) if mutex.try_lock # our thread won the race, let's get the value begin data[:value] = original.bind(self).call data[:timestamp] = ExpiringMemoize.gettime ensure mutex.unlock end else # our thread lost, block on the mutex and try again mutex.synchronize {} next end end return data[:value] end end end