Class: Farce::Concurrent::CyclicBarrier
- Inherits:
-
Object
- Object
- Farce::Concurrent::CyclicBarrier
- Includes:
- Internal::Noncopyable, Shareable::Delegated
- Defined in:
- lib/farce/concurrent/cyclic_barrier.rb
Overview
A replacement for concurrent-ruby's CyclicBarrier implementation.
Instance Attribute Summary collapse
-
#parties ⇒ Integer
readonly
The number of parties required to trip the barrier.
Instance Method Summary collapse
-
#broken? ⇒ Boolean
Whether the barrier is in a broken state.
-
#initialize(parties) { ... } ⇒ CyclicBarrier
constructor
A new instance of CyclicBarrier.
-
#number_waiting ⇒ Integer
The number of parties currently waiting at the barrier.
-
#reset ⇒ nil
Breaks the current generation and starts a new one.
-
#wait(timeout = nil) ⇒ Boolean
Waits for all parties to reach the barrier.
Methods included from Internal::Noncopyable
Methods included from Shareable
Constructor Details
#initialize(parties) { ... } ⇒ CyclicBarrier
Returns a new instance of CyclicBarrier.
45 46 47 48 49 50 51 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 45 def initialize(parties, &) raise ArgumentError, "parties must be a positive integer" unless parties.is_a?(Integer) && parties.positive? @parties = parties @action = block_given? ? Ractor.shareable_proc(&) : nil @generation = Strict::Atom.new(Generation.new) super() end |
Instance Attribute Details
#parties ⇒ Integer (readonly)
Returns the number of parties required to trip the barrier.
38 39 40 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 38 def parties @parties end |
Instance Method Details
#broken? ⇒ Boolean
Returns whether the barrier is in a broken state.
54 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 54 def broken? = generation.state == :broken |
#number_waiting ⇒ Integer
Returns the number of parties currently waiting at the barrier.
57 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 57 def number_waiting = generation.number_waiting |
#reset ⇒ nil
Breaks the current generation and starts a new one. Existing waiters return false.
94 95 96 97 98 99 100 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 94 def reset update do |current| current.state = :broken Generation.new end nil end |
#wait(timeout = nil) ⇒ Boolean
Waits for all parties to reach the barrier. Successful generations can be reused immediately. A timeout breaks the barrier for all waiters until #reset is called.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/farce/concurrent/cyclic_barrier.rb', line 63 def wait(timeout = nil) # rubocop:disable Naming/PredicateMethod deadline = Internal.timeout_deadline(timeout) waiting = nil update do |current| waiting = current next current unless current.state == :waiting current.waiting.increment next current if current.waiting.value < @parties completed = false begin @action&.call completed = true ensure current.state = completed ? :fulfilled : :broken end Generation.new end unless waiting.wait(Clock.remaining(deadline)) update do |current| # A trip or reset may have won the race with this waiter's timeout. waiting.state = :broken if waiting.state == :waiting current end end waiting.state == :fulfilled end |