Class: Farce::Abstract::ConcurrentMap Abstract

Inherits:
Map
  • Object
show all
Includes:
DuplicableMap
Defined in:
lib/farce/abstract/concurrent_map.rb,
lib/farce/integrations/active_support/map.rb

Overview

This class is abstract.

Super class for maps with added concurrency features.

Maps implement most of the interface provided by Hash, as well as Concurrent::Map from the concurrent-ruby gem.

ActiveSupport Integration collapse

Methods included from DuplicableMap

#compact_blank, #deep_dup, #duplicable?, #reverse_merge, #stringify_keys, #symbolize_keys, #with_indifferent_access

Methods inherited from Map

#as_json, #assert_valid_keys, #to_query

Instance Method Summary collapse

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, #length, #rassoc, #shareable_keys?, #shareable_values?, #to_a, #to_bson, #to_bson_normalized_value, #to_cbor, #to_h, #to_hash, #to_json, #to_msgpack, #to_s, #value?, #values_at, #weak_keys?, #weak_values?

Instance Method Details

#[](key) ⇒ BasicObject?

This method is abstract.

Look up a key without waiting for atomic-update access.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (BasicObject, nil) —

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



18
# File 'lib/farce/abstract/concurrent_map.rb', line 18

def [](key) = internal_map[key]

#[]=(key, value) ⇒ BasicObject

This method is abstract.

Associate a value with a key without a timeout.

Parameters:

  • key (BasicObject) —

    The key to store.

  • value (BasicObject) —

    The value to store.

Returns:

  • (BasicObject) —

    value.



21
22
23
# File 'lib/farce/abstract/concurrent_map.rb', line 21

def []=(key, value)
  internal_map[key] = value
end

#clear ⇒ self

This method is abstract.

Remove all entries from the map.

Returns:

  • (self)


363
364
365
366
# File 'lib/farce/abstract/concurrent_map.rb', line 363

def clear
  internal_map.clear
  self
end

#compact! ⇒ self?

Remove nil values using per-key update coordination. False values are retained. The whole operation is not atomic, as with #delete_if.

Returns:

  • (self, nil) —

    self if this operation deletes entries, otherwise nil.



396
# File 'lib/farce/abstract/concurrent_map.rb', line 396

def compact! = reject! { |_, value| nil.equal?(value) }

#compact_blank! ⇒ self

Note:

This methods is only available if ActiveSupport has been loaded.

Remove blank values using per-key coordination. Always return self. The operation is not atomic across keys.

Returns:

  • (self)


131
# File 'lib/farce/integrations/active_support/map.rb', line 131

def compact_blank! = delete_if { |_, value| value.blank? }

#compare_and_set(key, expected, replacement, timeout: nil) ⇒ Boolean

Atomically replace a value if the key is present and its current value matches expected. The configured value-comparison mode determines whether matching uses equality or identity.

Parameters:

  • key (BasicObject) —

    The key to update.

  • expected (BasicObject) —

    The value expected to be currently associated with the key.

  • replacement (BasicObject) —

    The value to store when the current value matches.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Returns:

  • (Boolean) —

    Whether the value was replaced. Returns false on timeout.



174
175
176
# File 'lib/farce/abstract/concurrent_map.rb', line 174

def compare_and_set(key, expected, replacement, timeout: nil)
  internal_map.compare_and_set(key, expected, replacement, timeout:)
end

#compare_keys_by_identity? ⇒ Boolean

This method is abstract.

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?.



306
# File 'lib/farce/abstract/concurrent_map.rb', line 306

def compare_keys_by_identity? = internal_map.compare_keys_by_identity?

#compare_values_by_identity? ⇒ Boolean

This method is abstract.

Returns Whether values are compared by identity instead of equality.

Returns:

  • (Boolean) —

    Whether values are compared by identity instead of equality.



309
# File 'lib/farce/abstract/concurrent_map.rb', line 309

def compare_values_by_identity? = internal_map.compare_values_by_identity?

#compute {|value| ... } ⇒ BasicObject?

Atomically replace the value associated with a key with the block result. The block receives nil when the key is absent or its current value is nil.

Parameters:

  • key (BasicObject) —

    The key to update.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called after access is acquired.

Yield Parameters:

  • value (BasicObject, nil) —

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

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject, nil) —

    The newly stored value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



207
# File 'lib/farce/abstract/concurrent_map.rb', line 207

def compute(...) = update(...)

#compute_if_absent { ... } ⇒ BasicObject?

Atomically fetch an existing value or compute and store a value for an absent key.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called without arguments when the key is absent.

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject, nil) —

    The existing or newly stored value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



105
# File 'lib/farce/abstract/concurrent_map.rb', line 105

def compute_if_absent(...) = store_if_absent(...)

#compute_if_present {|value| ... } ⇒ BasicObject?

Atomically replace the value associated with a key if it is present. The block receives the current value and should return the new value to store. The block is not called for an absent key. A stored nil is passed to the block.

Parameters:

  • key (BasicObject) —

    The key to update.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called with the current value if the key is present.

Yield Parameters:

  • value (BasicObject) —

    The current value.

Yield Returns:

  • (BasicObject) —

    The new value to store.

Returns:

  • (BasicObject, nil) —

    The newly stored value, or nil if the key was absent or the operation timed out.

Raises:

  • (LocalJumpError) —

    If no block is given.



165
# File 'lib/farce/abstract/concurrent_map.rb', line 165

def compute_if_present(...) = store_if_present(...)

#delete(key) ⇒ BasicObject?

This method is abstract.

Remove a key and its associated value.

Parameters:

  • key (BasicObject) —

    The key to remove.

Returns:

  • (BasicObject, nil) —

    The removed value, or nil if the key was absent.



360
# File 'lib/farce/abstract/concurrent_map.rb', line 360

def delete(key) = internal_map.delete(key)

#delete_if {|key, value| ... } ⇒ self, Enumerator

Delete entries selected by the block and return self.

Keys are captured before iteration. Each block and its decision use the existing atomic-update coordination. Blocks see the current value, and keys deleted before their turn are skipped. The whole operation is not atomic. Exceptions leave earlier changes in place. The same reentrancy restrictions as #update apply inside each block.

Yield Parameters:

  • key (BasicObject) —

    the stored key

  • value (BasicObject) —

    the current value

Returns:

  • (self, Enumerator)


378
379
380
381
382
383
# File 'lib/farce/abstract/concurrent_map.rb', line 378

def delete_if(&)
  return enum_for(__method__) { size } unless block_given?
  check_frozen! if respond_to?(:check_frozen!, true)
  filter_entries(&)
  self
end

#delete_pair(key, expected, timeout: nil) ⇒ Boolean

Atomically remove a key if its current value matches expected. The configured value-comparison mode determines whether matching uses equality or identity. Missing keys and mismatched values are left unchanged.

Parameters:

  • key (BasicObject) —

    The key to remove.

  • expected (BasicObject) —

    The expected current value.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Returns:

  • (Boolean) —

    Whether the entry was removed. Returns false on timeout.



188
189
190
191
192
193
# File 'lib/farce/abstract/concurrent_map.rb', line 188

def delete_pair(key, expected, timeout: nil)
  expected = wrap_comparison(expected)
  internal_map.modify(key, timeout:) do |present, value|
    present && values_equal?(value, expected) ? Internal::MAP_DELETE : Internal::MAP_KEEP
  end
end

#each(&block) ⇒ BasicObject Also known as: each_pair

Iterate over entries captured when iteration begins. The map can be modified safely from the block. (see Map#each)



321
322
323
324
325
326
# File 'lib/farce/abstract/concurrent_map.rb', line 321

def each(&block)
  return enum_for(__callee__) { size } unless block

  internal_map.each(&block)
  self
end

#each_key {|key| ... } ⇒ self #each_key ⇒ Enumerator

This method is abstract.

Iterate over the keys currently stored in the map. Keys are not guaranteed to be yielded in insertion order.

Overloads:

  • #each_key {|key| ... } ⇒ self

    Yields:

    • (key) —

      Called once for each stored key.

    Yield Parameters:

    • key (BasicObject) —

      A stored key.

    Returns:

    • (self)
  • #each_key ⇒ Enumerator

    Returns An enumerator over the stored keys.

    Returns:

    • (Enumerator) —

      An enumerator over the stored keys.



344
345
346
347
348
349
# File 'lib/farce/abstract/concurrent_map.rb', line 344

def each_key(&block)
  return enum_for(__callee__) { size } unless block

  internal_map.each_key(&block)
  self
end

#each_value {|value| ... } ⇒ self #each_value ⇒ Enumerator

This method is abstract.

Iterate over the values currently stored in the map. Values are not guaranteed to be yielded in insertion order.

Overloads:

  • #each_value {|value| ... } ⇒ self

    Yields:

    • (value) —

      Called once for each stored value.

    Yield Parameters:

    • value (BasicObject) —

      A stored value.

    Returns:

    • (self)
  • #each_value ⇒ Enumerator

    Returns An enumerator over the stored values.

    Returns:

    • (Enumerator) —

      An enumerator over the stored values.



352
353
354
355
356
357
# File 'lib/farce/abstract/concurrent_map.rb', line 352

def each_value(&block)
  return enum_for(__callee__) { size } unless block

  internal_map.each_value(&block)
  self
end

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

This method is abstract.

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.

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.



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/farce/abstract/concurrent_map.rb', line 26

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
  internal_map.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_or_store(key, *defaults) {|key| ... } ⇒ BasicObject?

Return an existing value or store a default for an absent key. A block takes precedence over the default and receives the original key. The lookup and store are separate operations. Concurrent writes can be overwritten.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

  • defaults (Array<BasicObject>) —

    At most one default value to store when the key is absent.

Yield Parameters:

  • key (BasicObject) —

    The original key.

Yield Returns:

  • (BasicObject) —

    The value to store.

Returns:

  • (BasicObject, nil) —

    The existing or newly stored value.

Raises:

  • (KeyError) —

    If the key is absent and neither a default nor a block is provided.

See Also:



50
51
52
53
54
55
56
# File 'lib/farce/abstract/concurrent_map.rb', line 50

def fetch_or_store(key, *defaults, **)
  if defaults.size > 1
    raise ArgumentError, "wrong number of arguments (given #{defaults.size + 1}, expected 1..2)"
  end
  return fetch(key) if defaults.empty? && !block_given?
  fetch(key) { store(key, block_given? ? yield(key) : defaults.first, **) }
end

#get(key, timeout: nil) { ... } ⇒ BasicObject?

Read the value associated with a key, waiting for atomic-update access if necessary.

Parameters:

  • key (BasicObject) —

    The key to look up.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called if access cannot be acquired before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    The associated value, nil if the key is absent, or the fallback result if the operation times out.



65
# File 'lib/farce/abstract/concurrent_map.rb', line 65

def get(key, timeout: nil, &) = internal_map.get(key, timeout:, &)

#get_and_set ⇒ BasicObject?

Sets a value and returns the previous value.

Parameters:

  • key (BasicObject) —

    The key to update.

  • value (BasicObject) —

    The value to store.

Returns:

  • (BasicObject, nil) —

    The previous value, or nil if the key was absent.



71
# File 'lib/farce/abstract/concurrent_map.rb', line 71

def get_and_set(...) = swap(...)

#getkey(key) ⇒ BasicObject?

This method is abstract.

Return the stored key that matches a lookup key.

Parameters:

  • key (BasicObject) —

    The key to match.

Returns:

  • (BasicObject, nil) —

    The matching stored key, or nil if no key matches.



300
# File 'lib/farce/abstract/concurrent_map.rb', line 300

def getkey(key) = internal_map.getkey(key)

#keep_if ⇒ self, Enumerator

Keep entries selected by the block. Uses the same coordination as #delete_if.

Returns:

  • (self, Enumerator)


400
401
402
403
404
405
# File 'lib/farce/abstract/concurrent_map.rb', line 400

def keep_if
  return enum_for(__method__) { size } unless block_given?
  check_frozen! if respond_to?(:check_frozen!, true)
  filter_entries { |key, value| !yield(key, value) }
  self
end

#key?(key) ⇒ Boolean

This method is abstract.

Test whether a key is present, including when its associated value is nil.

Parameters:

  • key (BasicObject) —

    The key to look up.

Returns:

  • (Boolean) —

    Whether the key is present.



297
# File 'lib/farce/abstract/concurrent_map.rb', line 297

def key?(key) = internal_map.key?(key)

#keys ⇒ Array<BasicObject>

This method is abstract.

Return the keys currently stored in the map. The returned keys are not guaranteed to be in insertion order.

Returns:

  • (Array<BasicObject>) —

    A new array containing the stored keys.



312
# File 'lib/farce/abstract/concurrent_map.rb', line 312

def keys = internal_map.keys

#merge!(*others) {|key, old_value, new_value| ... } ⇒ self

Apply input maps in order. A block resolves each collision under atomic-update coordination.

Incoming keys use normal lookup rules. Values use this map's transfer mode, including move semantics. The operation is not atomic across keys. Exceptions leave earlier changes in place.

Parameters:

  • others (Array<Map, Hash, #to_hash>) —

    mappings to apply in order

Yield Parameters:

  • key (BasicObject) —

    the incoming key

  • old_value (BasicObject) —

    the current value

  • new_value (BasicObject) —

    the incoming value

Returns:

  • (self)


444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/farce/abstract/concurrent_map.rb', line 444

def merge!(*others)
  check_frozen! if respond_to?(:check_frozen!, true)
  others.each do |other|
    unless Map === other
      other = Hash.try_convert(other) || raise(TypeError, "input must be a Map, Hash, or respond to #to_hash")
    end
    other.each_pair do |key, value|
      if block_given?
        modify_entry(key) { |present, old| present ? yield(key, old, value) : value }
      else
        self[key] = value
      end
    end
  end
  self
end

#merge_pair {|value| ... } ⇒ BasicObject?

Atomically insert initial for an absent key or replace an existing value with the block result. The block is not called when the key is absent.

Parameters:

  • key (BasicObject) —

    The key to insert or update.

  • initial (BasicObject) —

    The value to store when the key is absent.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called when the key is present.

Yield Parameters:

  • value (BasicObject) —

    The current value.

Yield Returns:

  • (BasicObject) —

    The replacement value to store and return.

Returns:

  • (BasicObject, nil) —

    The initial or replacement value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



222
# File 'lib/farce/abstract/concurrent_map.rb', line 222

def merge_pair(...) = upsert(...)

#put { ... } ⇒ BasicObject?

Associate a value with a key, waiting for atomic-update access if necessary.

Parameters:

  • key (BasicObject) —

    The key to store.

  • value (BasicObject) —

    The value to store.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called if access cannot be acquired before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    value on success, or the fallback result or nil on timeout.



83
# File 'lib/farce/abstract/concurrent_map.rb', line 83

def put(...) = store(...)

#put_if_absent(key, value) ⇒ BasicObject?

Atomically store a value only when the key is absent. Existing nil and false values are preserved.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

  • value (BasicObject) —

    The value to store when the key is absent.

Returns:

  • (BasicObject, nil) —

    The existing value, or nil when a value was inserted or access timed out.

See Also:



113
114
115
116
117
118
119
120
# File 'lib/farce/abstract/concurrent_map.rb', line 113

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

#reject! ⇒ self, ...

Like #delete_if, but return nil when this operation deletes no entries.

Returns:

  • (self, nil, Enumerator)


387
388
389
390
391
# File 'lib/farce/abstract/concurrent_map.rb', line 387

def reject!(&)
  return enum_for(__method__) { size } unless block_given?
  check_frozen! if respond_to?(:check_frozen!, true)
  self if filter_entries(&)
end

#replace_if_exists(key, replacement, timeout: nil) ⇒ BasicObject?

Atomically replace an existing value and return its previous value. An absent key is left unchanged. Existing nil and false values can be replaced.

Parameters:

  • key (BasicObject) —

    The key to update.

  • replacement (BasicObject) —

    The value to store.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Returns:

  • (BasicObject, nil) —

    The previous value, or nil when the key is absent or access timed out.

See Also:



129
130
131
132
133
134
135
136
137
138
139
# File 'lib/farce/abstract/concurrent_map.rb', line 129

def replace_if_exists(key, replacement, timeout: nil, **)
  map = internal_map
  previous = nil
  changed = map.modify(key, timeout:) do |present, value|
    next Internal::MAP_KEEP unless present
    previous = value
    map.check_mutation
    wrap_value(replacement, **)
  end
  unwrap_value(previous) if changed
end

#replace_pair ⇒ Boolean

Atomically replace a value if the key is present and its current value matches expected. The configured value-comparison mode determines whether matching uses equality or identity.

Parameters:

  • key (BasicObject) —

    The key to update.

  • expected (BasicObject) —

    The value expected to be currently associated with the key.

  • replacement (BasicObject) —

    The value to store when the current value matches.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait for access.

Returns:

  • (Boolean) —

    Whether the value was replaced. Returns false on timeout.



179
# File 'lib/farce/abstract/concurrent_map.rb', line 179

def replace_pair(...) = compare_and_set(...)

#reverse_merge!(other) ⇒ self Also known as: with_defaults!

Note:

This methods is only available if ActiveSupport has been loaded.

Store each default only if its key is absent, preserving existing nil and false values. Each decision is atomic for its key. Earlier changes survive exceptions. Inserted values use the map's transfer mode, including move semantics.

Parameters:

Returns:

  • (self)


139
140
141
142
143
144
145
# File 'lib/farce/integrations/active_support/map.rb', line 139

def reverse_merge!(other)
  unless Map === other
    other = Hash.try_convert(other) || raise(TypeError, "input must be a Map, Hash, or respond to #to_hash")
  end
  other.each_pair { |key, value| store_if_absent(key) { value } }
  self
end

#select! ⇒ self, ... Also known as: filter!

Like #keep_if, but return nil when this operation deletes no entries.

Returns:

  • (self, nil, Enumerator)


409
410
411
412
413
# File 'lib/farce/abstract/concurrent_map.rb', line 409

def select!
  return enum_for(__method__) { size } unless block_given?
  check_frozen! if respond_to?(:check_frozen!, true)
  self if filter_entries { |key, value| !yield(key, value) }
end

#size ⇒ Integer

This method is abstract.

Return the number of entries currently in the map.

Returns:

  • (Integer) —

    The number of entries.



303
# File 'lib/farce/abstract/concurrent_map.rb', line 303

def size = internal_map.size

#store(key, value, timeout: nil) { ... } ⇒ BasicObject?

Associate a value with a key, waiting for atomic-update access if necessary.

Parameters:

  • key (BasicObject) —

    The key to store.

  • value (BasicObject) —

    The value to store.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called if access cannot be acquired before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    value on success, or the fallback result or nil on timeout.



80
# File 'lib/farce/abstract/concurrent_map.rb', line 80

def store(key, value, timeout: nil, &) = internal_map.store(key, value, timeout:, &)

#store_if_absent(key, timeout: nil) { ... } ⇒ BasicObject?

Atomically fetch an existing value or compute and store a value for an absent key.

Parameters:

  • key (BasicObject) —

    The key to look up or store.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called without arguments when the key is absent.

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject, nil) —

    The existing or newly stored value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



102
# File 'lib/farce/abstract/concurrent_map.rb', line 102

def store_if_absent(key, timeout: nil, &) = internal_map.store_if_absent(key, timeout:, &)

#store_if_present(key, timeout: nil) {|value| ... } ⇒ BasicObject?

Atomically replace the value associated with a key if it is present. The block receives the current value and should return the new value to store. The block is not called for an absent key. A stored nil is passed to the block.

Parameters:

  • key (BasicObject) —

    The key to update.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called with the current value if the key is present.

Yield Parameters:

  • value (BasicObject) —

    The current value.

Yield Returns:

  • (BasicObject) —

    The new value to store.

Returns:

  • (BasicObject, nil) —

    The newly stored value, or nil if the key was absent or the operation timed out.

Raises:

  • (LocalJumpError) —

    If no block is given.



151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/farce/abstract/concurrent_map.rb', line 151

def store_if_present(key, timeout: nil)
  raise LocalJumpError, "no block given" unless block_given?
  map = internal_map
  result = nil
  changed = map.modify(key, timeout:) do |present, value|
    next Internal::MAP_KEEP unless present
    replacement = yield(unwrap_value(value))
    map.check_mutation
    result = wrap_value(replacement)
  end
  unwrap_value(result) if changed
end

#swap(key, replacement, timeout: nil) { ... } ⇒ BasicObject?

Replace the value associated with a key and return its previous value.

Parameters:

  • key (BasicObject) —

    The key to update.

  • replacement (BasicObject) —

    The value to store.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • Called if access cannot be acquired before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    The previous value, nil if the key was absent, or the fallback result if the operation times out.



93
# File 'lib/farce/abstract/concurrent_map.rb', line 93

def swap(key, replacement, timeout: nil, &) = internal_map.swap(key, replacement, timeout:, &)

#transform_values! {|value| ... } ⇒ self, Enumerator

Replace each existing value with the block result using atomic-update coordination.

Keys are captured before iteration. Missing keys are skipped and earlier changes survive exceptions. Results use this map's transfer mode. The same reentrancy restrictions as #update apply.

Yield Parameters:

  • value (BasicObject) —

    the current value

Returns:

  • (self, Enumerator)


423
424
425
426
427
428
429
430
431
432
# File 'lib/farce/abstract/concurrent_map.rb', line 423

def transform_values!
  return enum_for(__method__) { size } unless block_given?
  check_frozen! if respond_to?(:check_frozen!, true)
  keys.each do |key|
    modify_entry(key, canonical: true) do |present, value|
      present ? yield(value) : Internal::MAP_KEEP
    end
  end
  self
end

#update(key, timeout: nil) {|value| ... } ⇒ BasicObject?

Atomically replace the value associated with a key with the block result. The block receives nil when the key is absent or its current value is nil.

Parameters:

  • key (BasicObject) —

    The key to update.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called after access is acquired.

Yield Parameters:

  • value (BasicObject, nil) —

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

Yield Returns:

  • (BasicObject) —

    The value to store and return.

Returns:

  • (BasicObject, nil) —

    The newly stored value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



204
# File 'lib/farce/abstract/concurrent_map.rb', line 204

def update(key, timeout: nil, &) = internal_map.update(key, timeout:, &)

#upsert(key, initial, timeout: nil) {|value| ... } ⇒ BasicObject?

Atomically insert initial for an absent key or replace an existing value with the block result. The block is not called when the key is absent.

Parameters:

  • key (BasicObject) —

    The key to insert or update.

  • initial (BasicObject) —

    The value to store when the key is absent.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait for access.

Yields:

  • (value) —

    Called when the key is present.

Yield Parameters:

  • value (BasicObject) —

    The current value.

Yield Returns:

  • (BasicObject) —

    The replacement value to store and return.

Returns:

  • (BasicObject, nil) —

    The initial or replacement value, or nil on timeout.

Raises:

  • (LocalJumpError) —

    If no block is given.



219
# File 'lib/farce/abstract/concurrent_map.rb', line 219

def upsert(key, initial, timeout: nil, &) = internal_map.upsert(key, initial, timeout:, &)

#values ⇒ Array<BasicObject>

Return the values currently stored in the map.

Returns:

  • (Array<BasicObject>) —

    A new array of values in iteration order.



316
# File 'lib/farce/abstract/concurrent_map.rb', line 316

def values = each_value.to_a

#wait_until(key, timeout: nil) {|value| ... } ⇒ BasicObject?

Wait until a block condition matches the current value. One timeout budget covers all checks and waits. The block is not interrupted. An absent key is observed as nil.

Parameters:

  • key (BasicObject) —

    the key to observe

  • timeout (Numeric, nil) (defaults to: nil) —

    the total seconds available

Yield Parameters:

  • value (BasicObject, nil) —

    the current value

Yield Returns:

  • (Boolean) —

    whether the value matches

Returns:

  • (BasicObject, nil) —

    the matching value, or nil on timeout

Raises:

  • (LocalJumpError) —

    if no block is given



233
# File 'lib/farce/abstract/concurrent_map.rb', line 233

def wait_until(key, timeout: nil, &) = Internal.wait_until(self, key, timeout:, &)

#wait_until_changed(key, expected, timeout: nil) { ... } ⇒ BasicObject?

Wait until the value associated with a key no longer matches expected. An absent key is observed as nil. The configured value-comparison mode determines how values are matched.

Parameters:

  • key (BasicObject) —

    The key to observe.

  • expected (BasicObject) —

    The value to wait to change from.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait.

Yields:

  • Called if the value has not changed before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    The changed value, or the fallback result or nil on timeout.



284
285
286
# File 'lib/farce/abstract/concurrent_map.rb', line 284

def wait_until_changed(key, expected, timeout: nil, &)
  internal_map.wait_until_changed(key, expected, timeout:, &)
end

#wait_until_match(key, object, timeout: nil) ⇒ BasicObject?

Wait until object === value is true.

Parameters:

  • object (#===) —

    the pattern to match

  • timeout (Numeric, nil) (defaults to: nil) —

    the total seconds available

Returns:

  • (BasicObject, nil) —

    the matching value, or nil on timeout



272
273
274
# File 'lib/farce/abstract/concurrent_map.rb', line 272

def wait_until_match(key, object, timeout: nil)
  wait_until(key, timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
end

#wait_until_non_nil(key, timeout: nil) { ... } ⇒ BasicObject?

Wait until a key is associated with a non-nil value.

Parameters:

  • key (BasicObject) —

    The key to observe.

  • timeout (Numeric, nil) (defaults to: nil) —

    The maximum number of seconds to wait.

Yields:

  • Called if the value is still nil when the timeout elapses.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    The non-nil value, or the fallback result or nil on timeout.



294
# File 'lib/farce/abstract/concurrent_map.rb', line 294

def wait_until_non_nil(key, timeout: nil, &) = internal_map.wait_until_non_nil(key, timeout:, &)

#wait_until_value(key, object, timeout: nil) ⇒ BasicObject?

Wait until the current value equals an object using the configured comparison mode.

Parameters:

  • key (BasicObject) —

    the key to observe

  • object (BasicObject, nil) —

    the value to compare with the current value

  • timeout (Numeric, nil) (defaults to: nil) —

    the total seconds available

Returns:

  • (BasicObject, nil) —

    the matching value, or nil on timeout



264
265
266
# File 'lib/farce/abstract/concurrent_map.rb', line 264

def wait_until_value(key, object, timeout: nil)
  wait_until(key, timeout:) { |value| compare_values_by_identity? ? object.equal?(value) : object == value }
end

#wait_while(key, timeout: nil) {|value| ... } ⇒ BasicObject?

Wait while the block returns a truthy value.

Parameters:

  • key (BasicObject) —

    the key to observe

  • timeout (Numeric, nil) (defaults to: nil) —

    the total seconds available

Yield Parameters:

  • value (BasicObject, nil) —

    the current value

Yield Returns:

  • (BasicObject) —

    a truthy value to keep waiting, or nil or false to stop

Returns:

  • (BasicObject, nil) —

    the value when the condition becomes false, or nil on timeout

Raises:

  • (LocalJumpError) —

    if no block is given



242
243
244
245
# File 'lib/farce/abstract/concurrent_map.rb', line 242

def wait_while(key, timeout: nil)
  raise LocalJumpError, "no block given" unless block_given?
  wait_until(key, timeout:) { |value| !yield(value) }
end

#wait_while_match(key, object, timeout: nil) ⇒ BasicObject?

Wait while object === value is true.

Parameters:

  • key (BasicObject) —

    the key to observe

  • object (#===) —

    the pattern to stop matching

  • timeout (Numeric, nil) (defaults to: nil) —

    the total seconds available

Returns:

  • (BasicObject, nil) —

    the first nonmatching value, or nil on timeout



252
253
254
# File 'lib/farce/abstract/concurrent_map.rb', line 252

def wait_while_match(key, object, timeout: nil)
  wait_while(key, timeout:) { |value| object === value } # rubocop:disable Style/CaseEquality
end

#wait_while_value { ... } ⇒ BasicObject?

Wait until the value associated with a key no longer matches expected. An absent key is observed as nil. The configured value-comparison mode determines how values are matched.

Parameters:

  • key (BasicObject) —

    The key to observe.

  • expected (BasicObject) —

    The value to wait to change from.

  • timeout (Numeric, nil) —

    The maximum number of seconds to wait.

Yields:

  • Called if the value has not changed before the timeout.

Yield Returns:

  • (BasicObject) —

    The fallback value to return.

Returns:

  • (BasicObject, nil) —

    The changed value, or the fallback result or nil on timeout.



257
# File 'lib/farce/abstract/concurrent_map.rb', line 257

def wait_while_value(...) = wait_until_changed(...)