Class: AtomicRuby::AtomicCountDownLatch

Inherits:
Object
  • Object
show all
Defined in:
lib/atomic-ruby/atomic_count_down_latch.rb

Overview

Note:

This class is Ractor-safe in Ruby 4.0+ when compiled with ractor support.

Provides a countdown synchronization primitive using atomic operations.

AtomicCountDownLatch is a synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes. The latch is initialized with a count, and threads can wait for the count to reach zero or decrement the count atomically.

Examples:

Basic usage

latch = AtomicCountDownLatch.new(3)

# Start 3 worker threads
3.times do |worker_id|
  Thread.new do
    puts "Worker #{worker_id} starting"
    sleep(rand(2))
    puts "Worker #{worker_id} finished"
    latch.count_down
  end
end

latch.wait # Wait for all workers to complete
puts "All workers finished!"

Waiting for initialization

latch = AtomicCountDownLatch.new(1)

# Start initialization in background
Thread.new do
  puts "Initializing..."
  sleep(2)
  puts "Initialization complete"
  latch.count_down
end

puts "Waiting for initialization..."
latch.wait
puts "Ready to proceed!"

Defined Under Namespace

Classes: AlreadyCountedDownError, Error

Instance Method Summary collapse

Constructor Details

#initialize(count) ⇒ AtomicCountDownLatch

Creates a new countdown latch with the specified count.

Examples:

latch = AtomicCountDownLatch.new(5)  # Wait for 5 events
latch = AtomicCountDownLatch.new(1)  # Simple binary latch

Invalid usage

AtomicCountDownLatch.new(0)   #=> raises ArgumentError
AtomicCountDownLatch.new(-1)  #=> raises ArgumentError

Parameters:

  • count (Integer)

    The initial count value (must be positive)

Raises:

  • (ArgumentError)

    if count is not a positive integer



67
68
69
70
71
72
73
74
75
# File 'lib/atomic-ruby/atomic_count_down_latch.rb', line 67

def initialize(count)
  unless count.is_a?(Integer) && count > 0
    raise ArgumentError, "count must be a positive Integer"
  end

  @count = Atom.new(count)

  Ractor.make_shareable(self) if RACTOR_SAFE
end

Instance Method Details

#countInteger

Returns the current count value.

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:

latch = AtomicCountDownLatch.new(3)
puts latch.count #=> 3
latch.count_down
puts latch.count #=> 2

Returns:

  • (Integer)

    The current count (0 or positive)



92
93
94
# File 'lib/atomic-ruby/atomic_count_down_latch.rb', line 92

def count
  @count.value
end

#count_downInteger

Atomically decrements the count by one.

If the count reaches zero, any threads waiting on #wait will be unblocked. This operation uses compare-and-swap to ensure atomicity and prevent race conditions.

Examples:

latch = AtomicCountDownLatch.new(2)
latch.count_down #=> 1
latch.count_down #=> 0
latch.count_down #=> raises AlreadyCountedDownError

Thread-safe countdown

latch = AtomicCountDownLatch.new(10)
10.times do
  Thread.new { latch.count_down }
end

Returns:

  • (Integer)

    The new count value after decrementing

Raises:



119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/atomic-ruby/atomic_count_down_latch.rb', line 119

def count_down
  already_counted_down = false
  new_count = @count.swap do |current_count|
    if current_count == 0
      already_counted_down = true
      current_count
    else
      current_count - 1
    end
  end
  raise AlreadyCountedDownError, "already counted down to zero" if already_counted_down

  new_count
end

#waitvoid

This method returns an undefined value.

Blocks the current thread until the count reaches zero.

This method will block the calling thread until other threads have called #count_down enough times to reduce the count to zero. The method uses busy-waiting (Thread.pass) to check the count.

Examples:

Simple wait

latch = AtomicCountDownLatch.new(1)

Thread.new do
  sleep(2)
  latch.count_down
end

latch.wait # Blocks for ~2 seconds
puts "Latch opened!"

Waiting for multiple events

latch = AtomicCountDownLatch.new(3)

3.times do |event_id|
  Thread.new do
    sleep(1 + event_id)
    puts "Event #{event_id} completed"
    latch.count_down
  end
end

latch.wait # Waits for all 3 events
puts "All events completed!"


168
169
170
# File 'lib/atomic-ruby/atomic_count_down_latch.rb', line 168

def wait
  Thread.pass while @count.value > 0
end