Class: Concurrent::CyclicBarrier

Inherits:
Synchronization::LockableObject
  • Object
show all
Defined in:
lib/concurrent/atomic/cyclic_barrier.rb

Overview

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

Instance Method Summary collapse

Constructor Details

#initialize(parties) { ... } ⇒ CyclicBarrier

Create a new ‘CyclicBarrier` that waits for `parties` threads

Parameters:

  • parties (Fixnum)

    the number of parties

Yields:

  • an optional block that will be executed that will be executed after the last thread arrives and before the others are released

Raises:

  • (ArgumentError)

    if ‘parties` is not an integer or is less than zero



20
21
22
23
24
25
26
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 20

def initialize(parties, &block)
  if !parties.is_a?(Fixnum) || parties < 1
    raise ArgumentError.new('count must be in integer greater than or equal zero')
  end
  super(&nil)
  synchronize { ns_initialize parties, &block }
end

Instance Method Details

#broken?Boolean

A barrier can be broken when:

  • a thread called the ‘reset` method while at least one other thread was waiting

  • at least one thread timed out on ‘wait` method

A broken barrier can be restored using ‘reset` it’s safer to create a new one

Returns:

  • (Boolean)

    true if the barrier is broken otherwise false



85
86
87
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 85

def broken?
  synchronize { @generation.status != :waiting }
end

#number_waitingFixnum

Returns the number of threads currently waiting on the barrier.

Returns:

  • (Fixnum)

    the number of threads currently waiting on the barrier



34
35
36
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 34

def number_waiting
  synchronize { @number_waiting }
end

#partiesFixnum

Returns the number of threads needed to pass the barrier.

Returns:

  • (Fixnum)

    the number of threads needed to pass the barrier



29
30
31
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 29

def parties
  synchronize { @parties }
end

#resetnil

resets the barrier to its initial state If there is at least one waiting thread, it will be woken up, the ‘wait` method will return false and the barrier will be broken If the barrier is broken, this method restores it to the original state

Returns:

  • (nil)


75
76
77
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 75

def reset
  synchronize { ns_generation_done @generation, :reset }
end

#wait(timeout = nil) ⇒ Boolean

Blocks on the barrier until the number of waiting threads is equal to ‘parties` or until `timeout` is reached or `reset` is called If a block has been passed to the constructor, it will be executed once by

the last arrived thread before releasing the others

Parameters:

  • timeout (Fixnum) (defaults to: nil)

    the number of seconds to wait for the counter or ‘nil` to block indefinitely

Returns:

  • (Boolean)

    ‘true` if the `count` reaches zero else false on `timeout` or on `reset` or if the barrier is broken



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/concurrent/atomic/cyclic_barrier.rb', line 46

def wait(timeout = nil)
  synchronize do

    return false unless @generation.status == :waiting

    @number_waiting += 1

    if @number_waiting == @parties
      @action.call if @action
      ns_generation_done @generation, :fulfilled
      true
    else
      generation = @generation
      if ns_wait_until(timeout) { generation.status != :waiting }
        generation.status == :fulfilled
      else
        ns_generation_done generation, :broken, false
        false
      end
    end
  end
end