Timer implementation

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

Robert L. wrote:

                @condition.wait(@mutex, now_in_milliseconds) while @timer_list.empty?

Whoops, the above should of course be:
@condition.wait(@mutex, milliseconds_to_sleep)

In article [email protected],
Robert L. [email protected] writes:

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.

In ruby 1.9, timeout argument can be implemented as follows.

Index: lib/thread.rb

— lib/thread.rb (revision 24783)
+++ lib/thread.rb (working copy)
@@ -59,13 +59,16 @@

Releases the lock held in +mutex+ and waits; reacquires the lock on

wakeup.

  • def wait(mutex)
  • If +timeout+ is given, this method returns after +timeout+ seconds

passed,

  • even if no other thread doesn’t signal.

  • def wait(mutex, timeout=nil)
    begin
    # TODO: mutex should not be used
    @waiters_mutex.synchronize do
    @waiters.push(Thread.current)
    end
  •  mutex.sleep
    
  •  mutex.sleep timeout
    
    end
    end

On Thursday 10 September 2009 04:15:08 am Robert L. wrote:

I have implemented it like this:
def initialize(invoke_time, block)
end
an_hour = 60 * 60 * 1000
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

Hi Robert. I have a simple timer that I built awhile ago. It uses a
single
thread for timed events, and a thread pool for executing blocks. If you
are
looking to build your own, the source can probably help give you some
ideas.

Project:
http://rubyforge.org/projects/actiontimer

Source:

  • spox