Hi all

I am porting a timer class that I wrote in Java many years ago but I cannot see how to implement it in Ruby.

What I want is a single thread, that sleeps forever or until the next timer block should be called or until a new timer block i added.
The thread should be woken when a new timer block is added because it might be the next one to be called.

I have implemented it like this:

#!/usr/bin/ruby

require 'thread'
require 'bsearch'

class Timer
    class TimerObject
        attr_reader :invoke_time, :block

        def initialize(invoke_time, block)
            @invoke_time, @block = invoke_time, block
        end
    end

    def initialize
        @timer_list = []
        @mutex = Mutex.new
        @condition = ConditionVariable.new
        @running = false
        start
    end

    def stop
        running = false
        @mutex.synchronize { @condition.signal }
    end

    def start
        @running = true
        Thread.new do
            @mutex.synchronize do
                an_hour = 60 * 60 * 1000
                while running
                    now_in_milliseconds = (Time.now.to_f * 1000).to_i
                    milliseconds_to_sleep = @timer_list.empty? ? an_hour : @timer_list.first.invoke_time - now_in_milliseconds
                    @condition.wait(@mutex, now_in_milliseconds) while @timer_list.empty?

                    now_in_milliseconds = (Time.now.to_f * 1000).to_i
                    while @time_list.empty? == false and @time_list.first.invoke_time < now_in_milliseconds
                        @time_list.delete_at(0).block.call
                    end
                end
            end
        end
    end

    def postpone (timeout, &block)
        now = (Time.now.to_f * 1000).to_i
        time = now + timeout

        timerobject = TimerObject.new time, block

        @mutex.synchronize do
            idx = @timer_list.bsearch_lower_boundary { |x| x.invoke_time <=> time }
            @timer_list.insert(idx, timerobject) unless idx.nil?
            @timer_list << timerobject if idx.nil?
            @condition.signal
        end
    end
end


BUT...the 'start' method does not work since 'ConditionVariable' does not have a 'wait' method that takes a maximum wait time in milliseconds like we have in Java.

Any ideas as to how this can be done ?
Or is there a better way ?

I really don't want a thread per timer.

Best regards,
Robert