Skip to content

Instantly share code, notes, and snippets.

@davidcornu
Last active August 29, 2015 14:06
Show Gist options
  • Save davidcornu/05f765f2866be752ea5c to your computer and use it in GitHub Desktop.
Save davidcornu/05f765f2866be752ea5c to your computer and use it in GitHub Desktop.
Ruby timer thread
require 'thread'
class Clock
def self.timestamp
Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
end
class Timer
def initialize(timeout)
@expires_at = Clock.timestamp + timeout
@done_queue = Queue.new
end
def done?
!@done_queue.empty?
end
def update!(timestamp)
if timestamp >= @expires_at
@done_queue << true
end
end
end
def initialize
@new_timers = Queue.new
@worker = start_worker
end
def new_timer(timeout)
timer = Timer.new(timeout)
@new_timers << timer
timer
end
private
def start_worker
t = Thread.new do
timers = []
loop do
until @new_timers.empty? do
timers << @new_timers.pop
end
if timers.empty?
timers << @new_timers.pop
else
timestamp = Clock.timestamp
timers.reject! do |t|
t.update!(timestamp)
t.done?
end
sleep 0.01
end
end
end
t.abort_on_exception = true
t
end
end
# Usage -----------------
start = Clock.timestamp
clock = Clock.new
timers = (1..4).map { |s| clock.new_timer(s * 1000) }
while true
states = timers.map(&:done?)
puts states.map { |b| b ? 'y' : 'n' }.join(' | ')
break if states.all?
sleep 0.5
end
puts "Done in #{Clock.timestamp - start}ms"
@davidcornu
Copy link
Author

Output:

n | n | n | n
n | n | n | n
n | n | n | n
y | n | n | n
y | y | n | n
y | y | n | n
y | y | n | n
y | y | y | n
y | y | y | y
Done in 4007ms

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment