rf-web/vendor/bundle/gems/concurrent-ruby-1.1.5/lib/concurrent/atomic/event.rb
2019-10-21 10:18:17 +02:00

110 lines
2.8 KiB
Ruby

require 'thread'
require 'concurrent/synchronization'
module Concurrent
# Old school kernel-style event reminiscent of Win32 programming in C++.
#
# When an `Event` is created it is in the `unset` state. Threads can choose to
# `#wait` on the event, blocking until released by another thread. When one
# thread wants to alert all blocking threads it calls the `#set` method which
# will then wake up all listeners. Once an `Event` has been set it remains set.
# New threads calling `#wait` will return immediately. An `Event` may be
# `#reset` at any time once it has been set.
#
# @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682655.aspx
# @example
# event = Concurrent::Event.new
#
# t1 = Thread.new do
# puts "t1 is waiting"
# event.wait(1)
# puts "event ocurred"
# end
#
# t2 = Thread.new do
# puts "t2 calling set"
# event.set
# end
#
# [t1, t2].each(&:join)
#
# # prints:
# # t2 calling set
# # t1 is waiting
# # event occurred
class Event < Synchronization::LockableObject
# Creates a new `Event` in the unset state. Threads calling `#wait` on the
# `Event` will block.
def initialize
super
synchronize { ns_initialize }
end
# Is the object in the set state?
#
# @return [Boolean] indicating whether or not the `Event` has been set
def set?
synchronize { @set }
end
# Trigger the event, setting the state to `set` and releasing all threads
# waiting on the event. Has no effect if the `Event` has already been set.
#
# @return [Boolean] should always return `true`
def set
synchronize { ns_set }
end
def try?
synchronize { @set ? false : ns_set }
end
# Reset a previously set event back to the `unset` state.
# Has no effect if the `Event` has not yet been set.
#
# @return [Boolean] should always return `true`
def reset
synchronize do
if @set
@set = false
@iteration +=1
end
true
end
end
# Wait a given number of seconds for the `Event` to be set by another
# thread. Will wait forever when no `timeout` value is given. Returns
# immediately if the `Event` has already been set.
#
# @return [Boolean] true if the `Event` was set before timeout else false
def wait(timeout = nil)
synchronize do
unless @set
iteration = @iteration
ns_wait_until(timeout) { iteration < @iteration || @set }
else
true
end
end
end
protected
def ns_set
unless @set
@set = true
ns_broadcast
end
true
end
def ns_initialize
@set = false
@iteration = 0
end
end
end