|
#!/usr/local/bin/ruby19
|
|
|
|
require 'monitor'
|
|
|
|
Thread.abort_on_exception = true
|
|
|
|
# Process the given block in another thread (!) but at most the
|
|
# given number of seconds. If processing takes longer the result
|
|
# is discarded.
|
|
def timeout_1(timeout, &code)
|
|
raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
|
|
raise ArgumentError, "No code to execute" if code.nil?
|
|
|
|
worker = Thread.new(&code)
|
|
worker.join(timeout) and worker.value
|
|
end
|
|
|
|
# Process the given block in another thread (!) but at most the
|
|
# given number of seconds. If processing takes longer the result
|
|
# is discarded.
|
|
def timeout_2(timeout, &code)
|
|
raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
|
|
raise ArgumentError, "No code to execute" if code.nil?
|
|
|
|
mon = Monitor.new
|
|
cv = mon.new_cond
|
|
|
|
worker = Thread.new do
|
|
begin
|
|
code.call
|
|
ensure
|
|
mon.synchronize { cv.signal }
|
|
end
|
|
end
|
|
|
|
mon.synchronize do
|
|
cv.wait(timeout)
|
|
end ? worker.value : nil
|
|
end
|
|
|
|
# Process the given block in another thread (!) but at most the
|
|
# given number of seconds. If processing takes longer the result
|
|
# is discarded.
|
|
def timeout_3(timeout, &code)
|
|
raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
|
|
raise ArgumentError, "No code to execute" if code.nil?
|
|
|
|
mon = Mutex.new
|
|
cv = ::ConditionVariable.new
|
|
|
|
worker = Thread.new do
|
|
begin
|
|
code.call
|
|
ensure
|
|
mon.synchronize { cv.signal }
|
|
end
|
|
end
|
|
|
|
mon.synchronize do
|
|
cv.wait(mon, timeout)
|
|
end ? worker.value : nil
|
|
end
|
|
|
|
# Process the given block in another thread (!) but at most the
|
|
# given number of seconds. If processing takes longer the result
|
|
# is discarded.
|
|
def timeout_4(timeout, &code)
|
|
raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
|
|
raise ArgumentError, "No code to execute" if code.nil?
|
|
|
|
mon = Monitor.new
|
|
cv = ::ConditionVariable.new
|
|
|
|
worker = Thread.new do
|
|
begin
|
|
code.call
|
|
ensure
|
|
mon.synchronize { cv.signal }
|
|
end
|
|
end
|
|
|
|
mon.synchronize do
|
|
cv.wait(mon, timeout)
|
|
end ? worker.value : nil
|
|
end
|
|
|
|
[1, 2, 4, 5].each do |sec|
|
|
printf "Test with %2ds...\n", sec
|
|
|
|
%w{timeout_1 timeout_2 timeout_3 timeout_4}.each do |meth|
|
|
begin
|
|
result = send meth, sec do
|
|
sleep 3
|
|
:success
|
|
end
|
|
|
|
printf "%-10s: %p", meth, result
|
|
print " ERROR!" unless (sec > 3) == (result == :success)
|
|
puts
|
|
rescue Exception => e
|
|
printf "ERROR: method %p: %p\n", meth, e
|
|
end
|
|
end
|
|
|
|
puts
|
|
end
|
|
|
|
|