This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
require 'timeout' # for Timeout::Error
|
||||
|
||||
# = Timer
|
||||
#
|
||||
# Provides a strightforward means for controlling time critical execution.
|
||||
# Can be used as a "stop watch" timer or as a "time bomb" timer:
|
||||
#
|
||||
# t = Timer.new(10) { raise Timeout::Error, "timeout!" }
|
||||
# t.start
|
||||
# : # done within 10sec timeout
|
||||
# t.stop
|
||||
# t.start
|
||||
# :
|
||||
# if condition then
|
||||
# t.reset #--> restart timer
|
||||
# end
|
||||
#
|
||||
# A class method is also provided for easily timing the exectuion of a block.
|
||||
#
|
||||
# Timer.time do |timer|
|
||||
# timer.total_time.round #=> 0
|
||||
#
|
||||
# sleep 1
|
||||
# timer.total_time.round #=> 1
|
||||
#
|
||||
# timer.stop
|
||||
# timer.total_time.round #=> 1
|
||||
#
|
||||
# sleep 1
|
||||
# timer.total_time.round #=> 1
|
||||
#
|
||||
# timer.start
|
||||
# timer.total_time.round #=> 1
|
||||
#
|
||||
# sleep 1
|
||||
# timer.total_time.round #=> 2
|
||||
# end
|
||||
#
|
||||
# Thanks to Paul Brannan for TimeLimit and Minero Aoki for Timer.
|
||||
# These two libraries served as models for building this class.
|
||||
|
||||
class Timer
|
||||
|
||||
#
|
||||
def initialize(time_limit=nil, &block)
|
||||
# standard timer
|
||||
@start_time = nil
|
||||
@end_time = nil
|
||||
@total_time = 0
|
||||
@runnning = nil
|
||||
# for using time limit
|
||||
@time_limit = time_limit
|
||||
@on_timeout = block
|
||||
@current_thread = nil
|
||||
@timer_thread = nil
|
||||
end
|
||||
|
||||
#
|
||||
attr_accessor :time_limit
|
||||
|
||||
#
|
||||
def start_time
|
||||
@start_time
|
||||
end
|
||||
|
||||
#
|
||||
def end_time
|
||||
@end_time
|
||||
end
|
||||
|
||||
#
|
||||
def on_timeout( &block )
|
||||
if block then
|
||||
@on_timeout = block
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Start the timer.
|
||||
def start
|
||||
@running = true
|
||||
@start_time = Time.now
|
||||
|
||||
limit if @time_limit
|
||||
|
||||
self
|
||||
|
||||
##if block_given? then
|
||||
## begin
|
||||
## yield( self )
|
||||
## ensure
|
||||
## stop
|
||||
## end
|
||||
##else
|
||||
## @time_limit
|
||||
##end
|
||||
end
|
||||
|
||||
# Establish a time limit on execution.
|
||||
def limit( time_limit=nil )
|
||||
if @time_limit || time_limit
|
||||
@current_thread = Thread.current
|
||||
@timer_thread = Thread.fork {
|
||||
sleep @time_limit
|
||||
if @on_timeout then
|
||||
@on_timeout.call @time_limit
|
||||
else
|
||||
@current_thread.raise Timeout::Error, "#{@time_limit} seconds past"
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# Kill time limit thread, if any.
|
||||
def defuse
|
||||
if @timer_thread
|
||||
#Thread.kill @timer_thread
|
||||
@timer_thread.kill
|
||||
@timer_thread = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Stops timer and returns total time.
|
||||
# If timer was not running returns false.
|
||||
def stop
|
||||
if @running
|
||||
defuse
|
||||
# record running time
|
||||
@end_time = Time.now
|
||||
@running = false
|
||||
@total_time += (@end_time - @start_time)
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
# Stops and resets the timer. If the timer was running
|
||||
# returns the total time. If not returns 0.
|
||||
def reset
|
||||
if running?
|
||||
r = stop
|
||||
else
|
||||
r = 0
|
||||
end
|
||||
@total_time = 0
|
||||
return r
|
||||
end
|
||||
|
||||
# Resets the time limit. Same as:
|
||||
#
|
||||
# t.stop
|
||||
# t.start
|
||||
#
|
||||
def reset_limit
|
||||
#stop
|
||||
#start
|
||||
defuse
|
||||
limit
|
||||
end
|
||||
|
||||
# Queries whether the timer is still running.
|
||||
def running?
|
||||
return @running
|
||||
end
|
||||
|
||||
# Queries whether the timer is still not running.
|
||||
def stopped?
|
||||
return !@running
|
||||
end
|
||||
|
||||
# Queries total recorded time of timer.
|
||||
def total_time
|
||||
if running? then
|
||||
return @total_time + (Time.now - @start_time)
|
||||
else
|
||||
return @total_time
|
||||
end
|
||||
end
|
||||
|
||||
# Takes a block and returns the total time it took to execute.
|
||||
def self.time
|
||||
yield( timer = Timer.new.start )
|
||||
return timer.total_time
|
||||
end
|
||||
|
||||
# Timer::Dummy - Dummy Timer (i.e. no real time limit)
|
||||
#--
|
||||
# TODO: Timer::Dummy needs some work.
|
||||
#++
|
||||
class Dummy < self
|
||||
def start
|
||||
if block_given? then
|
||||
yield
|
||||
else
|
||||
time_limit()
|
||||
end
|
||||
end
|
||||
|
||||
def stop
|
||||
false
|
||||
end
|
||||
end #class Dummy
|
||||
|
||||
end #class Timer
|
||||
|
||||
# Copyright (c) 2004 Rubyworks
|
||||
Reference in New Issue
Block a user