# Define a few basic "interchange" classes tha module Nodepile # Caches the result of named calculations and their parameters and provides # a crude flushing class CrudeCalculationCache # Used to disable use of cache by all instances of this class. Note that this # is extremely useful during testing. def self.global_disable_cache(flag) = @@universally_disable_cache = flag # @param disable_cache [Boolean] if truthy, then caching is never triggered # for this object def initialize(disable_cache: false) @h = Hash.new @disable_cache = disable_cache end # Empties the entire cache forcing recalculation of some or all entries # @param name [String,Symbol,nil] Name of the calculation or nil if all calculations # are to be flushed # @param params [] If empty, all cached values for the given name will be flushed def flush_cache(name = nil, *params) if key.nil? @h.clear elsif params.empty? @h.delete(name) # delete simple keys @h.delete{|(cname,*cparams)| cname == name } else @h.delete([key,*params]) end return nil end def form_cache_key(sym,*parms) = parms.empty? ? sym : [sym,*parms] def stuff_cache(val,sym,*parms) = @h[form_cache_key(sym,*parms)] = val def has_cache?(sym,*parms) = @h.include?(form_cache_key(sym,*parms)) def fetch_cache(sym,*parms) key = form_cache_key(sym,*parms) raise "This item is not in the cache #{key.inspect}" unless @h.include?(key) return @h[key] end # Will either retrieve the value matching these parameters from the cache # or will do the calculation, cache the value, and return the result def cache(sym,*parms) raise "Calculation block expected" unless block_given? key = form_cache_key(sym,*parms) if @h.include?(key) && !@disable_cache && !@@global_disable_cache return @h[key] else return @h[sym] = yield(*parms) end end @@global_disable_cache = false end end #module Nodepile