Class: AtomicRuby::Atom

Inherits:
Object
  • Object
show all
Defined in:
lib/atomic-ruby/atom.rb,
ext/atomic_ruby/atomic_ruby.c

Overview

Note:

This class is Ractor-safe in Ruby 4.0+ when compiled with ractor support. Values that cross ractor boundaries are automatically made shareable.

Provides atomic reference semantics using Compare-And-Swap (CAS) operations.

An Atom allows for lock-free, thread-safe updates to a single reference value. The core operation is #swap, which atomically updates the value based on the current value, retrying if another thread modifies it concurrently.

Examples:

Basic usage

atom = Atom.new(0)
atom.swap { |current_value| current_value + 1 }
puts atom.value #=> 1

Thread-safe counter

counter = Atom.new(0)
threads = 10.times.map do
  Thread.new { 100.times { counter.swap { |current_count| current_count + 1 } } }
end
threads.each(&:join)
puts counter.value #=> 1000

Non-mutating array operations

atom = Atom.new([])
atom.swap { |current_array| current_array + [1] }
atom.swap { |current_array| current_array + [2] }
puts atom.value #=> [1, 2]

Instance Method Summary collapse

Constructor Details

#initialize(value) ⇒ Atom

Creates a new atomic reference with the given initial value.

Examples:

atom = Atom.new(42)
atom = Atom.new([1, 2, 3])
atom = Atom.new({ key: "value" })

Parameters:

  • value (untyped)

    The initial value to store atomically



45
46
47
# File 'lib/atomic-ruby/atom.rb', line 45

def initialize(value)
  _initialize(value)
end

Instance Method Details

#swap {|current_value| ... } ⇒ untyped

Atomically updates the value using a compare-and-swap operation.

The block receives the current value and must return the new value. If another thread modifies the atom between reading the current value and attempting to update it, the operation retries with the new current value.

Examples:

Increment a counter

atom = Atom.new(0)
new_value = atom.swap { |current_value| current_value + 1 }
puts new_value #=> 1

Append to array (non-mutating)

atom = Atom.new([1, 2])
atom.swap { |current_array| current_array + [3] }
puts atom.value #=> [1, 2, 3]

Conditional update

atom = Atom.new(10)
atom.swap { |current_value| current_value > 5 ? current_value * 2 : current_value }
puts atom.value #=> 20

Yield Parameters:

  • current_value (untyped)

    The current atomic value

Yield Returns:

  • (untyped)

    The new value to store atomically

Returns:

  • (untyped)

    The new value that was successfully stored



92
93
94
95
96
# File 'lib/atomic-ruby/atom.rb', line 92

def swap(&block)
  _swap do |old_value|
    make_shareable_if_needed(block.call(old_value))
  end
end

#valueuntyped

Returns the current value stored in the atom.

This operation is atomic and thread-safe. The returned value reflects the state at the time of the call, but may change immediately after in concurrent environments.

Examples:

atom = Atom.new("hello")
puts atom.value #=> "hello"

Returns:

  • (untyped)

    The current atomic value



62
63
64
# File 'lib/atomic-ruby/atom.rb', line 62

def value
  _value
end