=begin rdoc

= Time Limit

Provides a strightforward means for controlling time critical execution.

== Usage

  t = Time::Limit.new(10) { raise TimeoutError, "timeout!" }
  t.start
    :      # done within 10sec timeout
  t.stop
  t.start
    :
  if condition then
    t.reset       #--> restart timer
  end

== Legal

Based on Timer by Minero Aoki
Copyright (c) 1999-2002 Minero Aoki <aamine at loveruby.net>
  
This program is free software.
You can distribute/modify this program under the terms of
the GNU Lesser General Public License version 2 or later.
  
=end

require 'timeout'    # for TimeoutError


class Time

  #
  # Time::Limit
  #
  class Limit

    def initialize( s, &block )
      @sec = s
      @on_timeout = block
      @current = nil
      @timer_thread = nil
    end

    attr_accessor :sec

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

    def start
      @current = Thread.current
      @timer_thread = Thread.fork {
          sleep @sec
          if @on_timeout then
            @on_timeout.call @sec
          else
            @current.raise TimeoutError, "#{@sec} seconds past"
          end
      }
      if iterator? then
        begin
          yield
        ensure
          stop
        end
      else
        @sec
      end
    end

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

    def reset
      stop
      start
    end

    #
    # Dummy Time Limit
    #
    class Dummy < Limit
      def start
        if iterator? then
          yield
        else
          sec()
        end
      end

      def stop
        false
      end
    end #class Dummy

  end #class Limit

end #class Time