require 'thread'

# A synchronization barrier enables multiple threads to wait until all threads
# have all reached a particular point of execution before any thread
# continues.
class Barrier
  
  # Initialize new barrier. The _count_ argument specifies the number of threads
  # that must call #wait before any of them successfully return from the call.
  # The value specified by _count_ must be greater than zero.
  #
  # For example
  #   b = Barrier.new(3)
  #   3.times do
  #     Thread.new do
  #       print 1
  #       b.wait
  #       print 2
  #     end
  #   end
  #   sleep(1)
  #   puts
  # produce
  #   111222  
  def initialize(count)
    @count_max = count
    @count = 1
    @mutex = Mutex.new
    @lock = ConditionVariable.new
  end
  
  # The #wait function shall synchronize participating threads at the barrier.
  # The calling thread shall block until the required number of threads have
  # called #wait specifying the barrier.
  def wait
    @mutex.synchronize do
      if @count < @count_max
        @count += 1
        @lock.wait(@mutex)
      else
        @count = 1
        @lock.broadcast
      end
    end
    nil
  end
end
