Class: Concurrent::AtomicMarkableReference

Inherits:
Synchronization::Object
  • Object
show all
Defined in:
lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb

Overview

An atomic reference which maintains an object reference along with a mark bit that can be updated atomically.

Instance Method Summary collapse

Constructor Details

#initialize(value = nil, mark = false) ⇒ AtomicMarkableReference

Returns a new instance of AtomicMarkableReference.

 15 16 17 18
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 15 def initialize(value = nil, mark = false) super() self.reference = immutable_array(value, mark) end

Instance Method Details

#compare_and_set(expected_val, new_val, expected_mark, new_mark) ⇒ Boolean Also known as: compare_and_swap

Atomically sets the value and mark to the given updated value and mark given both:

  • the current value == the expected value &&
  • the current mark == the expected mark

that the actual value was not equal to the expected value or the actual mark was not equal to the expected mark

Parameters:

  • expected_val (Object)

    the expected value

  • new_val (Object)

    the new value

  • expected_mark (Boolean)

    the expected mark

  • new_mark (Boolean)

    the new mark

Returns:

  • (Boolean)

    true if successful. A false return indicates

 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 33 def compare_and_set(expected_val, new_val, expected_mark, new_mark) # Memoize a valid reference to the current AtomicReference for  # later comparison.  current = reference curr_val, curr_mark = current # Ensure that that the expected marks match.  return false unless expected_mark == curr_mark if expected_val.is_a? Numeric # If the object is a numeric, we need to ensure we are comparing  # the numerical values  return false unless expected_val == curr_val else # Otherwise, we need to ensure we are comparing the object identity.  # Theoretically, this could be incorrect if a user monkey-patched  # `Object#equal?`, but they should know that they are playing with  # fire at that point.  return false unless expected_val.equal? curr_val end prospect = immutable_array(new_val, new_mark) compare_and_set_reference current, prospect end

#getArray

Gets the current reference and marked values.

Returns:

  • (Array)

    the current reference and marked values

 64 65 66
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 64 def get reference end

#markBoolean Also known as: marked?

Gets the current marked value

Returns:

  • (Boolean)

    the current marked value

 78 79 80
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 78 def mark reference[1] end

#set(new_val, new_mark) ⇒ Array

Unconditionally sets to the given value of both the reference and the mark.

Parameters:

  • new_val (Object)

    the new value

  • new_mark (Boolean)

    the new mark

Returns:

  • (Array)

    both the new value and the new mark

 91 92 93
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 91 def set(new_val, new_mark) self.reference = immutable_array(new_val, new_mark) end

#try_update {|Object| ... } ⇒ Array

Pass the current value to the given block, replacing it with the block's result. Simply return nil if update fails.

the update failed

Yields:

  • (Object)

    Calculate a new value and marked state for the atomic reference using given (old) value and (old) marked

Yield Parameters:

  • old_val (Object)

    the starting value of the atomic reference

  • old_mark (Boolean)

    the starting state of marked

Returns:

  • (Array)

    the new value and marked state, or nil if

 152 153 154 155 156 157 158 159
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 152 def try_update old_val, old_mark = reference new_val, new_mark = yield old_val, old_mark return unless compare_and_set old_val, new_val, old_mark, new_mark immutable_array(new_val, new_mark) end

#try_update! {|Object| ... } ⇒ Array

Pass the current value to the given block, replacing it with the block's result. Raise an exception if the update fails.

Yields:

  • (Object)

    Calculate a new value and marked state for the atomic reference using given (old) value and (old) marked

Yield Parameters:

  • old_val (Object)

    the starting value of the atomic reference

  • old_mark (Boolean)

    the starting state of marked

Returns:

  • (Array)

    the new value and marked state

Raises:

 128 129 130 131 132 133 134 135 136 137 138 139 140
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 128 def try_update! old_val, old_mark = reference new_val, new_mark = yield old_val, old_mark unless compare_and_set old_val, new_val, old_mark, new_mark fail ::Concurrent::ConcurrentUpdateError, 'AtomicMarkableReference: Update failed due to race condition.', 'Note: If you would like to guarantee an update, please use ' + 'the `AtomicMarkableReference#update` method.' end immutable_array(new_val, new_mark) end

#update {|Object| ... } ⇒ Array

Pass the current value and marked state to the given block, replacing it with the block's results. May retry if the value changes during the block's execution.

Yields:

  • (Object)

    Calculate a new value and marked state for the atomic reference using given (old) value and (old) marked

Yield Parameters:

  • old_val (Object)

    the starting value of the atomic reference

  • old_mark (Boolean)

    the starting state of marked

Returns:

  • (Array)

    the new value and new mark

 105 106 107 108 109 110 111 112 113 114
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 105 def update loop do old_val, old_mark = reference new_val, new_mark = yield old_val, old_mark if compare_and_set old_val, new_val, old_mark, new_mark return immutable_array(new_val, new_mark) end end end

#valueObject

Gets the current value of the reference

Returns:

  • (Object)

    the current value of the reference

 71 72 73
# File 'lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb', line 71 def value reference[0] end