Class: Farce::WeakAtom
- Inherits:
-
Abstract::WeakAtom
- Object
- Abstract::Atom
- Abstract::WeakAtom
- Farce::WeakAtom
- Includes:
- Shareable::Delegated
- Defined in:
- lib/farce/weak_atom.rb
Overview
A Ractor-shareable atomic reference that retains its value weakly. Values support :raise (the default), :make_shareable, and :dedup. The value becomes nil after collection when no strong references remain. With :dedup, retain the canonical result returned by store or update. Keeping only the input alive may not keep the stored result alive. Assignment evaluates to the input rather than the canonical result. Comparisons observe the stored object without preparing their operands.
Instance Method Summary collapse
-
#compare_and_set(expected, replacement, mode: nil, timeout: nil) ⇒ Boolean
Atomically replace the current value if it matches the expected value.
-
#initialize(value = nil, mode: :raise, compare_by_identity: false) ⇒ WeakAtom
constructor
A new instance of WeakAtom.
-
#mode ⇒ Symbol
The default mode used to prepare replacement values.
-
#store(new_value, mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Store a new value, waiting for any update in progress.
-
#store_if_absent(mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Compute and store a value if the current value is nil.
-
#swap(new_value, mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Replace the current value and return the previous value.
-
#update(mode: nil, timeout: nil) {|current| ... } ⇒ BasicObject?
Atomically replace the current value with the result of a block.
-
#upsert(initial, mode: nil, timeout: nil) {|current| ... } ⇒ BasicObject?
Store an initial value if the current value is nil, otherwise replace it with the result of a block.
-
#wait_until_changed(expected, timeout: nil) { ... } ⇒ BasicObject?
Wait until the current value no longer matches an expected value.
Methods included from Shareable
Methods inherited from Abstract::Atom
#blank?, #compare_by_identity?, #get, #value, #value=, #wait_until, #wait_until_match, #wait_until_non_nil, #wait_until_value, #wait_while, #wait_while_match, #wait_while_value
Methods included from Internal::ValueSerialization
#as_extended_json, #as_json, #to_bson, #to_bson_normalized_value, #to_cbor, #to_json, #to_msgpack
Methods included from Abstract::Value
Methods included from Internal::Copyable
Constructor Details
#initialize(value = nil, mode: :raise, compare_by_identity: false) ⇒ WeakAtom
Returns a new instance of WeakAtom.
29 30 31 32 |
# File 'lib/farce/weak_atom.rb', line 29 def initialize(value = nil, mode: :raise, compare_by_identity: false) @manager = Internal::WeakModeManager.new(mode:) super(@manager.wrap(value), compare_by_identity:) end |
Instance Method Details
#compare_and_set(expected, replacement, mode: nil, timeout: nil) ⇒ Boolean
Atomically replace the current value if it matches the expected value.
90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/farce/weak_atom.rb', line 90 def compare_and_set(expected, replacement, mode: nil, timeout: nil) @manager.validate_mode!(mode) matched = false @atom.update(timeout:) do |current| next current unless values_equal?(current, expected) check_frozen! prepared = @manager.wrap(replacement, mode:) matched = true prepared end matched end |
#mode ⇒ Symbol
The default mode used to prepare replacement values.
36 |
# File 'lib/farce/weak_atom.rb', line 36 def mode = @manager.mode |
#store(new_value, mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Store a new value, waiting for any update in progress.
40 41 42 43 |
# File 'lib/farce/weak_atom.rb', line 40 def store(new_value, mode: nil, timeout: nil, &) check_frozen! super(@manager.wrap(new_value, mode:), timeout:, &) end |
#store_if_absent(mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Compute and store a value if the current value is nil.
54 55 56 57 58 59 60 61 62 |
# File 'lib/farce/weak_atom.rb', line 54 def store_if_absent(mode: nil, timeout: nil) raise LocalJumpError, "no block given" unless block_given? @manager.validate_mode!(mode) super(timeout:) do value = yield check_frozen! @manager.wrap(value, mode:) end end |
#swap(new_value, mode: nil, timeout: nil) { ... } ⇒ BasicObject?
Replace the current value and return the previous value.
47 48 49 50 |
# File 'lib/farce/weak_atom.rb', line 47 def swap(new_value, mode: nil, timeout: nil, &) check_frozen! super(@manager.wrap(new_value, mode:), timeout:, &) end |
#update(mode: nil, timeout: nil) {|current| ... } ⇒ BasicObject?
Atomically replace the current value with the result of a block.
66 67 68 69 70 71 72 73 74 |
# File 'lib/farce/weak_atom.rb', line 66 def update(mode: nil, timeout: nil) raise LocalJumpError, "no block given" unless block_given? @manager.validate_mode!(mode) super(timeout:) do |current| value = yield(current) check_frozen! @manager.wrap(value, mode:) end end |
#upsert(initial, mode: nil, timeout: nil) {|current| ... } ⇒ BasicObject?
Store an initial value if the current value is nil, otherwise replace it with the result of a block.
78 79 80 81 82 83 84 85 86 |
# File 'lib/farce/weak_atom.rb', line 78 def upsert(initial, mode: nil, timeout: nil) raise LocalJumpError, "no block given" unless block_given? @manager.validate_mode!(mode) @atom.update(timeout:) do |current| value = nil.equal?(current) ? initial : yield(current) check_frozen! @manager.wrap(value, mode:) end end |
#wait_until_changed(expected, timeout: nil) { ... } ⇒ BasicObject?
Wait until the current value no longer matches an expected value.
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/farce/weak_atom.rb', line 104 def wait_until_changed(expected, timeout: nil, &fallback) deadline = Internal.timeout_deadline(timeout) while true current = @atom.get(timeout: Internal.remaining_timeout(deadline)) { TIMED_OUT } return fallback&.call if TIMED_OUT.equal?(current) return current unless values_equal?(current, expected) result = @atom.wait_until_changed(current, timeout: Internal.remaining_timeout(deadline)) { TIMED_OUT } return fallback&.call if TIMED_OUT.equal?(result) end end |