Module: ExpiringMemoize
- Defined in:
- lib/expiring_memoize.rb,
lib/expiring_memoize/version.rb
Constant Summary collapse
- VERSION =
"0.1.1"
Class Method Summary collapse
Instance Method Summary collapse
-
#memoize(name, ttl: Float::INFINITY) ⇒ Object
Memoize a nullary method.
Class Method Details
.gettime ⇒ Object
40 41 42 |
# File 'lib/expiring_memoize.rb', line 40 def self.gettime Process.clock_gettime Process::CLOCK_MONOTONIC_COARSE end |
Instance Method Details
#memoize(name, ttl: Float::INFINITY) ⇒ Object
Memoize a nullary method.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# 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 |