class Concurrent::Atom

@see clojure.org/state Values and Change - Clojure’s approach to Identity and State
@see clojure.org/atoms Clojure Atoms
@!macro thread_safe_variable_comparison
Unlike in Clojure, ‘Atom` cannot participate in {Concurrent::TVar} transactions.
value.
not an error. It simply means that the change operation returned the same
completed. Note that `old_value` and `new_value` may be the same. This is
The `new_value` is the value to which the Atom was set when the change
occurred. The `old_value` is the value of the Atom when the change began
and `new_value`. The `time` argument is the time at which the value change
When notified the observer will receive three arguments: `time`, `old_value`,
Notification of observers occurs every time the value of the Atom changes.
Atoms support observers through the {Concurrent::Observable} mixin module.
## Observation
“`
atom.value #=> [0, 1, 1, 2, 3, 5, 8]
# get the current value
end
atom.swap{|set| next_fibonacci(set) }
5.times do
# send a few update requests
atom = Concurrent::Atom.new(next_fibonacci)
# create an atom with an initial value
end
set + [set.reduce{|sum,x| sum + x }]
return [0, 1] if set.nil?
def next_fibonacci(set = nil)
“`
## Example
value validates.
new value to the result of running the given block if and only if that
the current value matches the new value. The latter will atomically set the
{#swap}. The former will set the new value if and only if it validates and
There are two ways to change the value of an atom: {#compare_and_set} and
validator returns false or raises an exception.
will be checked against the validator and will be rejected if the
changed. If a validator is given at construction then any new value
proc. At any time the value of the atom can be synchronously and safely
An atom is initialized with an initial value and an optional validation
Atoms provide a way to manage shared, synchronous, independent state.

def compare_and_set(old_value, new_value)

Returns:
  • (Boolean) - True if the value is changed else false.

Parameters:
  • new_value (Object) -- The intended new value.
  • old_value (Object) -- The expected current value.
def compare_and_set(old_value, new_value)
  if valid?(new_value) && compare_and_set_value(old_value, new_value)
    observers.notify_observers(Time.now, old_value, new_value)
    true
  else
    false
  end
end

def initialize(value, opts = {})

Raises:
  • (ArgumentError) - if the validator is not a `Proc` (when given)

Options Hash: (**opts)
  • :validator (Proc) -- Optional proc used to validate new

Parameters:
  • opts (Hash) -- The options used to configure the atom
  • value (Object) -- The initial value
def initialize(value, opts = {})
  super()
  @Validator     = opts.fetch(:validator, -> v { true })
  self.observers = Collection::CopyOnNotifyObserverSet.new
  self.value     = value
end

def reset(new_value)

Returns:
  • (Object) - The final value of the atom after all operations and

Parameters:
  • new_value (Object) -- The intended new value.
def reset(new_value)
  old_value = value
  if valid?(new_value)
    self.value = new_value
    observers.notify_observers(Time.now, old_value, new_value)
    new_value
  else
    old_value
  end
end

def swap(*args)

Raises:
  • (ArgumentError) - When no block is given.

Returns:
  • (Object) - The final value of the atom after all operations and

Other tags:
    Yieldreturn: - The intended new value of the atom.

Other tags:
    Yieldparam: args - All arguments passed to the function, in order.
    Yieldparam: value - The current value of the atom.

Other tags:
    Yield: - Calculates a new value for the atom based on the

Parameters:
  • args (Object) -- Zero or more arguments passed to the block.

Other tags:
    Note: - The given block may be called multiple times, and thus should be free
def swap(*args)
  raise ArgumentError.new('no block given') unless block_given?
  loop do
    old_value = value
    new_value = yield(old_value, *args)
    begin
      break old_value unless valid?(new_value)
      break new_value if compare_and_set(old_value, new_value)
    rescue
      break old_value
    end
  end
end

def valid?(new_value)

Returns:
  • (Boolean) - false if the validator function returns false or raises

Parameters:
  • new_value (Object) -- The intended new value.
def valid?(new_value)
  @Validator.call(new_value)
rescue
  false
end