Class: Farce::Abstract::BoundedMap Abstract
- Includes:
- DuplicableMap
- Defined in:
- lib/farce/abstract/bounded_map.rb,
lib/farce/integrations/psych.rb,
lib/farce/integrations/active_support/map.rb
Overview
Superclass for maps that retain at most a configured number of entries.
Successful individual value reads and writes update the map's eviction policy. Observational operations such as iteration, #key?, and #getkey do not. Copies preserve capacity and eviction history without counting copying as an access.
Instance Method Summary collapse
-
#[](key) ⇒ BasicObject?
abstract
Look up a key without waiting for atomic-update access.
-
#[]=(key, value) ⇒ BasicObject
abstract
Associate a value with a key without a timeout.
-
#clear ⇒ self
abstract
Remove all entries from the map.
-
#compare_keys_by_identity? ⇒ Boolean
abstract
Whether keys are compared by identity instead of
hashandeql?. -
#compare_values_by_identity? ⇒ Boolean
abstract
Whether values are compared by identity instead of equality.
-
#delete(key) ⇒ BasicObject?
abstract
Remove a key and its associated value.
-
#each ⇒ BasicObject
(also: #each_pair)
Iterate over a snapshot without updating eviction history.
-
#each_key ⇒ self, Enumerator
Iterate over a snapshot of stored keys without updating eviction history.
-
#each_value ⇒ self, Enumerator
Iterate over a snapshot of stored values without updating eviction history.
-
#fetch(*arguments) ⇒ BasicObject
abstract
Fetch the value associated with a key, using the same missing-key behavior as Hash#fetch.
-
#getkey(key) ⇒ BasicObject?
abstract
Return the stored key that matches a lookup key.
-
#initialize(entries = nil, max_size:, normalize_keys: nil, compare_by_identity: false, compare_keys_by_identity: compare_by_identity, compare_values_by_identity: compare_by_identity) ⇒ BoundedMap
constructor
A new instance of BoundedMap.
-
#key?(key) ⇒ Boolean
abstract
Test whether a key is present, including when its associated value is nil.
-
#keys ⇒ Array<BasicObject>
Return a frozen snapshot of stored keys.
-
#max_size ⇒ Integer
Return the maximum number of entries retained by the current backing map.
-
#max_size=(limit) ⇒ Integer
Change the maximum number of retained entries and immediately evict any excess.
-
#prune(to:) ⇒ Integer
Remove entries selected by the eviction policy until at most
toremain. -
#shift ⇒ Array(BasicObject, BasicObject)?
Remove and return the next entry selected by the eviction policy.
-
#size ⇒ Integer
(also: #length)
abstract
Return the number of entries currently in the map.
-
#store_if_absent(key) ⇒ BasicObject
Return an existing value, or store the block result for an absent key.
-
#values ⇒ Array<BasicObject>
Return a frozen snapshot of stored values.
Methods included from DuplicableMap
#compact, #except, #flatten, #invert, #merge, #reject, #select, #slice, #to_proc, #transform_keys, #transform_values
Methods inherited from Map
#as_extended_json, #assoc, #bson_type, #compare_by_identity?, #deconstruct_keys, #dig, #empty?, #fetch_values, #has_key?, #key, #rassoc, #shareable_keys?, #shareable_values?, #store, #to_a, #to_bson, #to_bson_normalized_value, #to_cbor, #to_h, #to_hash, #to_json, #to_s, #value?, #values_at, #weak_keys?, #weak_values?
Constructor Details
#initialize(entries = nil, max_size:, normalize_keys: nil, compare_by_identity: false, compare_keys_by_identity: compare_by_identity, compare_values_by_identity: compare_by_identity) ⇒ BoundedMap
Returns a new instance of BoundedMap.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/farce/abstract/bounded_map.rb', line 22 def initialize( entries = nil, max_size:, normalize_keys: nil, compare_by_identity: false, compare_keys_by_identity: compare_by_identity, compare_values_by_identity: compare_by_identity ) entries = convert_entries(entries) @map = new_bounded_map( max_size:, compare_by_identity:, compare_keys_by_identity:, compare_values_by_identity:, ) @key_locks = new_key_locks(compare_keys_by_identity:) restoring = Internal::KeyNormalizer.restoration?(normalize_keys) normalizer = Internal::KeyNormalizer.build( normalize_keys, shareable: normalize_keys && Internal::KeyNormalizer.shareable_target?(self), ) Internal::KeyNormalizer.install(self, normalizer, Internal::KeyNormalizer::BoundedOperations) unless restoring entries&.each { self[_1] = _2 } Internal::KeyNormalizer.install(self, normalizer, Internal::KeyNormalizer::BoundedOperations) if restoring super() end |
Instance Method Details
#[](key) ⇒ BasicObject?
Look up a key without waiting for atomic-update access.
50 |
# File 'lib/farce/abstract/bounded_map.rb', line 50 def [](key) = unwrap_value(internal_map[prepare_key(key)]) |
#[]=(key, value) ⇒ BasicObject
Associate a value with a key without a timeout.
53 54 55 56 57 |
# File 'lib/farce/abstract/bounded_map.rb', line 53 def []=(key, value) key = prepare_store_key(key) with_key_lock(key) { internal_map[key] = wrap_value(value) } value end |
#clear ⇒ self
Remove all entries from the map.
93 94 95 96 |
# File 'lib/farce/abstract/bounded_map.rb', line 93 def clear internal_map.clear self end |
#compare_keys_by_identity? ⇒ Boolean
Returns Whether keys are compared by identity instead of hash and eql?.
99 |
# File 'lib/farce/abstract/bounded_map.rb', line 99 def compare_keys_by_identity? = internal_map.compare_keys_by_identity? |
#compare_values_by_identity? ⇒ Boolean
Returns Whether values are compared by identity instead of equality.
102 |
# File 'lib/farce/abstract/bounded_map.rb', line 102 def compare_values_by_identity? = internal_map.compare_values_by_identity? |
#delete(key) ⇒ BasicObject?
Remove a key and its associated value.
105 |
# File 'lib/farce/abstract/bounded_map.rb', line 105 def delete(key) = unwrap_value(internal_map.delete(prepare_key(key))) |
#each {|pair| ... } ⇒ self #each ⇒ Enumerator Also known as: each_pair
Iterate over a snapshot without updating eviction history.
165 166 167 168 169 |
# File 'lib/farce/abstract/bounded_map.rb', line 165 def each return enum_for(__method__) unless block_given? internal_map.each { |key, value| yield [key, unwrap_value(value)] } self end |
#each_key ⇒ self, Enumerator
Iterate over a snapshot of stored keys without updating eviction history.
174 175 176 177 178 |
# File 'lib/farce/abstract/bounded_map.rb', line 174 def each_key return enum_for(__method__) unless block_given? internal_map.each_key { yield it } self end |
#each_value ⇒ self, Enumerator
Iterate over a snapshot of stored values without updating eviction history.
182 183 184 185 186 |
# File 'lib/farce/abstract/bounded_map.rb', line 182 def each_value return enum_for(__method__) unless block_given? internal_map.each_value { yield unwrap_value(it) } self 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 and a warning is emitted.
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/farce/abstract/bounded_map.rb', line 108 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 prepared_key = prepare_key(key) warn "block supersedes default value argument", uplevel: 1 if block_given? && arguments.length == 2 value = internal_map.fetch(prepared_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 unwrap_value(value) end |
#getkey(key) ⇒ BasicObject?
Return the stored key that matches a lookup key.
125 |
# File 'lib/farce/abstract/bounded_map.rb', line 125 def getkey(key) = internal_map.getkey(prepare_key(key)) |
#key?(key) ⇒ Boolean
Test whether a key is present, including when its associated value is nil.
128 |
# File 'lib/farce/abstract/bounded_map.rb', line 128 def key?(key) = internal_map.key?(prepare_key(key)) |
#keys ⇒ Array<BasicObject>
Return a frozen snapshot of stored keys.
190 |
# File 'lib/farce/abstract/bounded_map.rb', line 190 def keys = each_key.to_a.freeze |
#max_size ⇒ Integer
Return the maximum number of entries retained by the current backing map.
132 |
# File 'lib/farce/abstract/bounded_map.rb', line 132 def max_size = internal_map.max_size |
#max_size=(limit) ⇒ Integer
Change the maximum number of retained entries and immediately evict any excess.
137 138 139 |
# File 'lib/farce/abstract/bounded_map.rb', line 137 def max_size=(limit) internal_map.max_size = limit end |
#prune(to:) ⇒ Integer
Remove entries selected by the eviction policy until at most to remain.
This does not change #max_size.
145 |
# File 'lib/farce/abstract/bounded_map.rb', line 145 def prune(to:) = internal_map.prune(to:) |
#shift ⇒ Array(BasicObject, BasicObject)?
Remove and return the next entry selected by the eviction policy.
149 150 151 152 |
# File 'lib/farce/abstract/bounded_map.rb', line 149 def shift pair = internal_map.shift [pair.first, unwrap_value(pair.last)] if pair end |
#size ⇒ Integer Also known as: length
Return the number of entries currently in the map.
155 |
# File 'lib/farce/abstract/bounded_map.rb', line 155 def size = internal_map.size |
#store_if_absent(key) ⇒ BasicObject
Return an existing value, or store the block result for an absent key. Coordinated implementations share one initialization among concurrent callers for equal keys. Unsafe implementations can run competing loaders. The block runs without holding the map's structural lock, so other keys remain accessible. Coordinated assignment waits for initialization. Deletion or clearing can precede a pending initialization's insertion. At zero capacity, coordinated implementations run equal-key loaders sequentially. Each loader validates and transfers its result, but the map retains no value.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/farce/abstract/bounded_map.rb', line 73 def store_if_absent(key) raise LocalJumpError, "no block given" unless block_given? map = internal_map found = true stored = map.fetch(prepare_key(key)) { found = false } return unwrap_value(stored) if found key = prepare_store_key(key) with_key_lock(key) do stored = map.fetch(key) do wrapped = wrap_value(yield) map[key] = wrapped return unwrap_value(wrapped) end unwrap_value(stored) end end |
#values ⇒ Array<BasicObject>
Return a frozen snapshot of stored values.
194 |
# File 'lib/farce/abstract/bounded_map.rb', line 194 def values = each_value.to_a.freeze |