Class: Farce::Strict::WeakCache

Inherits:
Object
  • Object
show all
Includes:
Farce::Shareable::Delegated, Internal::Inspect
Defined in:
lib/farce/strict/weak_cache.rb

Overview

A weak cache that allows reusing previously generated values without holding strong references to them. Only shareable keys and values can be used.

Examples:

cache = Farce::Strict::WeakCache.new
value = cache.store_if_absent(:key) { ExpensiveClass.new.freeze }

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Farce::Shareable

#ractor_shareable?

Constructor Details

#initialize(initial_mapping = nil, compare_by_identity: false) ⇒ WeakCache

Returns a new instance of WeakCache.

Parameters:

  • initial_mapping (Hash, Farce::Abstract::Map, #each, nil) (defaults to: nil) —

    The entries to store initially. Each iteration must yield a key-value pair. Nil creates an empty map.

  • compare_by_identity (Boolean) (defaults to: false) —

    Whether keys use object identity instead of hash and eql?.



27
28
29
30
31
# File 'lib/farce/strict/weak_cache.rb', line 27

def initialize(initial_mapping = nil, compare_by_identity: false)
  @map = Strict::WeakValueMap.new(initial_mapping, compare_keys_by_identity: compare_by_identity)
  initialize_cache
  super()
end

Class Method Details

.create ⇒ WeakCache, Strict::WeakValueMap

Creates a new WeakCache instance if it outperforms Farce::Strict::WeakValueMap on the current platform. Otherwise it creates a standard WeakValueMap instance.

Returns:



20
# File 'lib/farce/strict/weak_cache.rb', line 20

def self.create(...) = Internal.native_weak_maps? ? Strict::WeakValueMap.new(...) : WeakCache.new(...)

Instance Method Details

#[](key) ⇒ BasicObject?

Look up a value without generating it.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (BasicObject, nil) —

    The associated value, or nil if the key is absent.



76
# File 'lib/farce/strict/weak_cache.rb', line 76

def [](key) = @cache.fetch(key) { nil } # rubocop:disable Style/RedundantFetchBlock

#assoc(key) ⇒ Array(BasicObject, BasicObject)?

Return a lookup key and its associated value if present.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (Array(BasicObject, BasicObject), nil) —

    The pair [key, value], or nil if the key is absent.



81
82
83
84
# File 'lib/farce/strict/weak_cache.rb', line 81

def assoc(key)
  value = fetch(key) { return nil }
  [key, value]
end

#compare_by_identity? ⇒ Boolean

Returns Whether keys are compared by identity instead of hash and eql?.

Returns:

  • (Boolean) —

    Whether keys are compared by identity instead of hash and eql?.



163
# File 'lib/farce/strict/weak_cache.rb', line 163

def compare_by_identity? = compare_keys_by_identity?

#compare_keys_by_identity? ⇒ Boolean

Returns Whether keys are compared by identity instead of hash and eql?.

Returns:

  • (Boolean) —

    Whether keys are compared by identity instead of hash and eql?.



160
# File 'lib/farce/strict/weak_cache.rb', line 160

def compare_keys_by_identity? = @map.compare_keys_by_identity?

#dig(key, *rest) ⇒ BasicObject?

Look up a value in nested maps or arrays.

Parameters:

  • key (BasicObject) —

    The key to look up.

  • rest (Array<BasicObject>) —

    Additional keys or indices for the nested value.

Returns:

  • (BasicObject, nil) —

    The nested value, or nil if an intermediate value is absent or nil.



102
103
104
105
106
# File 'lib/farce/strict/weak_cache.rb', line 102

def dig(key, *rest)
  value = self[key]
  return value if rest.empty? || value.nil?
  value.dig(*rest)
end

#fetch(key) ⇒ BasicObject #fetch(key, default) ⇒ BasicObject #fetch(key) {|key| ... } ⇒ BasicObject

Fetch the value associated with a key, using the same missing-key behavior as Hash#fetch. If both a default and a block are provided, the block takes precedence.

Overloads:

  • #fetch(key) ⇒ BasicObject

    Returns The associated value.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    Returns:

    • (BasicObject) —

      The associated value.

    Raises:

    • (KeyError) —

      If the key is absent.

  • #fetch(key, default) ⇒ BasicObject

    Returns The associated value or default.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    • default (BasicObject) —

      The value to return if the key is absent.

    Returns:

    • (BasicObject) —

      The associated value or default.

  • #fetch(key) {|key| ... } ⇒ BasicObject

    Returns The associated value or the block result.

    Parameters:

    • key (BasicObject) —

      The key to look up.

    Yields:

    • (key) —

      Called if the key is absent.

    Yield Parameters:

    • key (BasicObject) —

      The missing key.

    Yield Returns:

    • (BasicObject) —

      The value to return.

    Returns:

    • (BasicObject) —

      The associated value or the block result.



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/farce/strict/weak_cache.rb', line 132

def fetch(*arguments)
  unless arguments.length.between?(1, 2)
    raise ArgumentError, "wrong number of arguments (given #{arguments.length}, expected 1..2)"
  end

  key, default = arguments
  warn "block supersedes default value argument", uplevel: 1 if block_given? && arguments.length == 2
  @cache.fetch(key) do
    return yield(key) if block_given?
    return default if arguments.length == 2
    raise KeyError.new("key not found: #{key.inspect}", receiver: self, key: key)
  end
end

#fetch_values(*keys) {|key| ... } ⇒ Array<BasicObject>

Fetch values in the requested order, using #fetch for missing keys.

Parameters:

  • keys (Array<BasicObject>) —

    The keys to look up.

Yields:

  • (key) —

    Called for each missing key.

Yield Parameters:

  • key (BasicObject) —

    The missing key.

Yield Returns:

  • (BasicObject) —

    The fallback value, which is not stored.

Returns:

  • (Array<BasicObject>) —

    The associated values or block results.



152
# File 'lib/farce/strict/weak_cache.rb', line 152

def fetch_values(*keys, &) = keys.map { fetch(it, &) }

#getkey(key) ⇒ BasicObject?

Return the stored key matching a lookup key.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (BasicObject, nil) —

    The stored key, or nil if the key is absent.



111
# File 'lib/farce/strict/weak_cache.rb', line 111

def getkey(key) = @map.getkey(key)

#key?(key) ⇒ Boolean Also known as: has_key?, include?, member?

Return whether a live entry exists, including entries with nil or false values.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (Boolean)


89
90
91
92
# File 'lib/farce/strict/weak_cache.rb', line 89

def key?(key)
  @cache.fetch(key) { return false }
  true
end

#put_if_absent(key, value) ⇒ BasicObject?

Store a value only when the key is absent. Existing nil and false values count as present.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

  • value (BasicObject) —

    The value to store if the key is absent.

Returns:

  • (BasicObject, nil) —

    The existing value, or nil when a value was inserted.



64
65
66
67
68
69
70
71
# File 'lib/farce/strict/weak_cache.rb', line 64

def put_if_absent(key, value)
  inserted = false
  previous = store_if_absent(key) do
    inserted = true
    value
  end
  inserted ? nil : previous
end

#shareable_keys? ⇒ Boolean

Returns Whether keys must be Ractor-shareable, including copied mutable strings.

Returns:

  • (Boolean) —

    Whether keys must be Ractor-shareable, including copied mutable strings.



166
# File 'lib/farce/strict/weak_cache.rb', line 166

def shareable_keys? = true

#shareable_values? ⇒ Boolean

Returns Whether values must be Ractor-shareable.

Returns:

  • (Boolean) —

    Whether values must be Ractor-shareable.



169
# File 'lib/farce/strict/weak_cache.rb', line 169

def shareable_values? = true

#store_if_absent(key) { ... } ⇒ BasicObject Also known as: compute_if_absent

Retrieves or stores a value for the given key. The block is called to generate the value if the key is absent. Concurrent calls for the same key reuse the generated value. Once that value is collected, a later call generates it again.

Parameters:

  • key (BasicObject) —

    The key to look up.

Yields:

  • Called without arguments when the key is absent.

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject) —

    The associated value.

Raises:

  • (LocalJumpError)


52
53
54
55
# File 'lib/farce/strict/weak_cache.rb', line 52

def store_if_absent(key, &)
  raise LocalJumpError, "no block given" unless block_given?
  @cache.store_if_absent(key, &)
end

#values_at(*keys) ⇒ Array<BasicObject>

Look up values in the requested order, returning nil for missing keys.

Parameters:

  • keys (Array<BasicObject>) —

    The keys to look up.

Returns:

  • (Array<BasicObject>) —

    The associated values, with nil for missing keys.



157
# File 'lib/farce/strict/weak_cache.rb', line 157

def values_at(*keys) = keys.map { self[it] }

#weak_keys? ⇒ Boolean

Returns Whether keys are referenced weakly.

Returns:

  • (Boolean) —

    Whether keys are referenced weakly.



172
# File 'lib/farce/strict/weak_cache.rb', line 172

def weak_keys? = false

#weak_values? ⇒ Boolean

Returns Whether values are referenced weakly.

Returns:

  • (Boolean) —

    Whether values are referenced weakly.



175
# File 'lib/farce/strict/weak_cache.rb', line 175

def weak_values? = true