# Timer implementation

**URL:** <https://www.ruby-forum.com/t/timer-implementation/175274>\
**Category:** Ruby\
**Created:** [September 10, 2009, 1:16pm UTC](https://www.ruby-forum.com/t/timer-implementation/175274 "2009-09-10T13:16:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [September 10, 2009, 1:16pm UTC](https://www.ruby-forum.com/t/timer-implementation/175274/1 "2009-09-10T13:16:17Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [September 10, 2009, 1:17pm UTC](https://www.ruby-forum.com/t/timer-implementation/175274/2 "2009-09-10T13:17:27Z")

</div>

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)

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [September 10, 2009, 5:16pm UTC](https://www.ruby-forum.com/t/timer-implementation/175274/3 "2009-09-10T17:16:54Z")

</div>

In article [4aa8deb2$0$25181$removed\_email\_address@domain.invalid](mailto:4aa8deb2$0$25181$removed_email_address@domain.invalid),  
Robert L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) 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

---

<div class="post-metadata">

**Author:** ![rlorimor](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/96bed5/32.png) [@rlorimor](https://www.ruby-forum.com/u/rlorimor)\
**Post date:** [September 10, 2009, 5:33pm UTC](https://www.ruby-forum.com/t/timer-implementation/175274/4 "2009-09-10T17:33:53Z")

</div>

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](http://rubyforge.org/projects/actiontimer)

Source:

> **[GitHub - spox/actiontimer: Simple timer for a complex world](https://github.com/spox/actiontimer)**
>
> Simple timer for a complex world. Contribute to spox/actiontimer development by creating an account on GitHub.

- spox
