class Concurrent::AtomicMarkableReference

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

@see docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicMarkableReference.html

java.util.concurrent.atomic.AtomicMarkableReference

Public Class Methods

new(value = nil, mark = false) click to toggle source
# 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

Public Instance Methods

compare_and_set(expected_val, new_val, expected_mark, new_mark) click to toggle source

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

@param [Object] expected_val the expected value @param [Object] new_val the new value @param [Boolean] expected_mark the expected mark @param [Boolean] new_mark the new mark

@return [Boolean] ‘true` if successful. A `false` return indicates that the actual value was not equal to the expected value or the actual mark was not equal to the expected mark

# 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
Also aliased as: compare_and_swap
compare_and_swap(expected_val, new_val, expected_mark, new_mark)
Alias for: compare_and_set
get() click to toggle source

Gets the current reference and marked values.

@return [Array] the current reference and marked values

# File lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb, line 64
def get
  reference
end
mark() click to toggle source

Gets the current marked value

@return [Boolean] the current marked value

# File lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb, line 78
def mark
  reference[1]
end
Also aliased as: marked?
marked?()
Alias for: mark
set(new_val, new_mark) click to toggle source

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

@param [Object] new_val the new value @param [Boolean] new_mark the new mark

@return [Array] both the new value and the new mark

# 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() { |old_val, old_mark| ... } click to toggle source

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

@yield [Object] Calculate a new value and marked state for the atomic

reference using given (old) value and (old) marked

@yieldparam [Object] old_val the starting value of the atomic reference @yieldparam [Boolean] old_mark the starting state of marked

@return [Array] the new value and marked state, or nil if the update failed

# 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!() { |old_val, old_mark| ... } click to toggle source

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

@yield [Object] Calculate a new value and marked state for the atomic

reference using given (old) value and (old) marked

@yieldparam [Object] old_val the starting value of the atomic reference @yieldparam [Boolean] old_mark the starting state of marked

@return [Array] the new value and marked state

@raise [Concurrent::ConcurrentUpdateError] if the update fails

# 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() { |old_val, old_mark| ... } click to toggle source

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.

@yield [Object] Calculate a new value and marked state for the atomic

reference using given (old) value and (old) marked

@yieldparam [Object] old_val the starting value of the atomic reference @yieldparam [Boolean] old_mark the starting state of marked

@return [Array] the new value and new mark

# 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
value() click to toggle source

Gets the current value of the reference

@return [Object] the current value of the reference

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

Private Instance Methods

immutable_array(*args) click to toggle source
# File lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb, line 163
def immutable_array(*args)
  args.freeze
end