Class: Phronomy::Runtime::TimerQueue

Inherits:
Object
  • Object
show all
Defined in:
lib/phronomy/runtime/timer_queue.rb

Overview

A thread-safe timer queue backed by a single background thread.

Replaces the pattern of spawning one +Thread.new { sleep(t); callback }+ per deadline. Any number of timers share a single background thread that sleeps until the earliest pending deadline.

Use #schedule to register a one-shot callback; call #shutdown when the queue is no longer needed (e.g. on process exit) to stop the background thread cleanly.

Instance Method Summary collapse

Constructor Details

#initialize(clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }) ⇒ TimerQueue

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of TimerQueue.

Parameters:

  • clock (#call) (defaults to: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) })

    zero-argument callable that returns the current monotonic time in seconds (defaults to +Process::CLOCK_MONOTONIC+). Override in tests to inject a fake clock.



19
20
21
22
23
24
25
26
27
# File 'lib/phronomy/runtime/timer_queue.rb', line 19

def initialize(clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) })
  @clock = clock
  @heap = [] # [[fire_at, callback], ...]
  @mutex = Mutex.new
  @cond = ConditionVariable.new
  @stopped = false
  @thread = Thread.new { run_loop }
  @thread.name = "phronomy-timer-queue"
end

Instance Method Details

#pending_countInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Number of pending (not yet fired) callbacks. Primarily for testing.

Returns:

  • (Integer)


61
62
63
# File 'lib/phronomy/runtime/timer_queue.rb', line 61

def pending_count
  @mutex.synchronize { @heap.size }
end

#schedule(seconds:, &callback) ⇒ self

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Schedule a one-shot callback to fire after +seconds+ from now.

Parameters:

  • seconds (Numeric)

    delay before the callback fires

Returns:

  • (self)


35
36
37
38
39
40
41
42
43
# File 'lib/phronomy/runtime/timer_queue.rb', line 35

def schedule(seconds:, &callback)
  fire_at = @clock.call + seconds.to_f
  @mutex.synchronize do
    raise Phronomy::PoolShutdownError, "TimerQueue has been shut down" if @stopped
    insert_sorted(fire_at, callback)
    @cond.signal
  end
  self
end

#shutdownself

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Stop the background thread. Pending (un-fired) callbacks are discarded.

Returns:

  • (self)


49
50
51
52
53
54
55
56
# File 'lib/phronomy/runtime/timer_queue.rb', line 49

def shutdown
  @mutex.synchronize do
    @stopped = true
    @cond.signal
  end
  @thread.join
  self
end