tmail/amstd/timer.rb

#
# timer.rb
#
#   Copyright (c) 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
#
#
# usage:
#
#   t = Timer.new(10){ raise TimeoutError, "timeout!" }
#   t.start
#     :      # done with 10sec timeout
#   t.stop
#
#   t.start
#     :
#   if condition then
#     t.reset       #--> restart timer
#   end
#

require 'timeout'    # for TimeoutError

require 'amstd/must'
require 'amstd/extmod'


class Timer

  def initialize( s, &block )
    self.sec = s
    self.on_timeout( &block )
  end


  property :sec, Numeric, true, true

  def start
    @cur = Thread.current
    @thr = Thread.fork{
      sleep @sec
      @on_timeout and @on_timeout.call( @sec )
    }
    if iterator? then
      yield
      stop
    else
      @sec
    end
  end

  def stop
    if @thr then
      Thread.kill @thr
      @thr = nil
      return true
    else
      return false
    end
  end

  def reset
    stop
    start
  end

  def on_timeout( &block )
    if block then
      @on_timeout = block
      return true
    else
      return false
    end
  end

end


class DammyTimer < Timer

  def start
    if iterator? then
      yield
      stop
    else
      @sec
    end
  end

  def stop
    false
  end

end


class TimeredBomb < Timer

  def initialize( s )
    super
    @on_timeout = proc{ @cur.raise TimeoutError, "#{@sec} seconds past" }
  end

  def on_timeout( &block )
    false
  end

end