class Concurrent::Edge::AtomicMarkableReference

@!macro [attach] atomic_markable_reference

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

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

@api Edge

Public Class Methods

new(value = nil, mark = false) click to toggle source

@!macro [attach] atomic_markable_reference_method_initialize

Calls superclass method
# File lib/concurrent/edge/atomic_markable_reference.rb, line 17
def initialize(value = nil, mark = false)
  super()
  self.reference = ImmutableArray[value, mark]
end

Public Instance Methods

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

@!macro [attach] atomic_markable_reference_method_compare_and_set

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/edge/atomic_markable_reference.rb, line 37
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 = ImmutableArray[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

@!macro [attach] atomic_markable_reference_method_get

Gets the current reference and marked values.

@return [ImmutableArray] the current reference and marked values
# File lib/concurrent/edge/atomic_markable_reference.rb, line 69
def get
  reference
end
mark() click to toggle source

@!macro [attach] atomic_markable_reference_method_mark

Gets the current marked value

@return [Boolean] the current marked value
# File lib/concurrent/edge/atomic_markable_reference.rb, line 87
def mark
  reference[1]
end
Also aliased as: marked?
marked?()
Alias for: mark
set(new_val, new_mark) click to toggle source

@!macro [attach] atomic_markable_reference_method_set

_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 [ImmutableArray] both the new value and the new mark
# File lib/concurrent/edge/atomic_markable_reference.rb, line 101
def set(new_val, new_mark)
  self.reference = ImmutableArray[new_val, new_mark]
end
try_update() { |old_val, old_mark| ... } click to toggle source

@!macro [attach] atomic_markable_reference_method_try_update

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 [ImmutableArray] the new value and marked state, or nil if the update failed

# File lib/concurrent/edge/atomic_markable_reference.rb, line 168
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

  ImmutableArray[new_val, new_mark]
end
try_update!() { |old_val, old_mark| ... } click to toggle source

@!macro [attach] atomic_markable_reference_method_try_update!

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 [ImmutableArray] the new value and marked state

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

# File lib/concurrent/edge/atomic_markable_reference.rb, line 142
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

  ImmutableArray[new_val, new_mark]
end
update() { |old_val, old_mark| ... } click to toggle source

@!macro [attach] atomic_markable_reference_method_update

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 [ImmutableArray] the new value and new mark

# File lib/concurrent/edge/atomic_markable_reference.rb, line 117
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 ImmutableArray[new_val, new_mark]
    end
  end
end
value() click to toggle source

@!macro [attach] atomic_markable_reference_method_value

Gets the current value of the reference

@return [Object] the current value of the reference
# File lib/concurrent/edge/atomic_markable_reference.rb, line 78
def value
  reference[0]
end