Class: Phronomy::Runtime::TimerQueue
- Inherits:
-
Object
- Object
- Phronomy::Runtime::TimerQueue
- Defined in:
- lib/phronomy/engine/runtime/timer_queue.rb
Overview
Threadless monotonic timer heap driven by EventLoop.
Instance Method Summary collapse
-
#fire_due ⇒ Object
Executes all callbacks whose deadline is due.
-
#initialize(clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }) ⇒ TimerQueue
constructor
A new instance of TimerQueue.
- #pending_count ⇒ Object
- #schedule(seconds:, &callback) ⇒ Object
-
#seconds_until_next ⇒ Object
Seconds until the next timer is due, nil when no timers are pending.
- #shutdown ⇒ Object
-
#wake_with(&block) ⇒ Object
Installs a lightweight wake callback used when a newly scheduled timer may change EventLoop's current wait deadline.
Constructor Details
#initialize(clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }) ⇒ TimerQueue
Returns a new instance of TimerQueue.
7 8 9 10 11 12 13 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 7 def initialize(clock: -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) }) @clock = clock @heap = [] @mutex = Mutex.new @stopped = false @wake = nil end |
Instance Method Details
#fire_due ⇒ Object
Executes all callbacks whose deadline is due. Must be called by EventLoop.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 48 def fire_due callbacks = @mutex.synchronize do return 0 if @stopped now = @clock.call due_count = @heap.bsearch_index { |(fire_at, _)| fire_at > now } || @heap.length @heap.shift(due_count).map(&:last) end callbacks.each do |callback| callback.call rescue => error Phronomy.configuration.logger&.error do "[TimerQueue] callback raised #{error.class}: #{error.}" end end callbacks.length end |
#pending_count ⇒ Object
67 68 69 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 67 def pending_count @mutex.synchronize { @heap.size } end |
#schedule(seconds:, &callback) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 22 def schedule(seconds:, &callback) raise ArgumentError, "schedule requires a block" unless callback fire_at = @clock.call + seconds.to_f wake = nil @mutex.synchronize do raise Phronomy::PoolShutdownError, "TimerQueue has been shut down" if @stopped previous_first = @heap.first&.first @heap << [fire_at, callback] @heap.sort_by!(&:first) wake = @wake if previous_first.nil? || fire_at < previous_first end wake&.call self end |
#seconds_until_next ⇒ Object
Seconds until the next timer is due, nil when no timers are pending.
40 41 42 43 44 45 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 40 def seconds_until_next @mutex.synchronize do return nil if @stopped || @heap.empty? [@heap.first.first - @clock.call, 0.0].max end end |
#shutdown ⇒ Object
71 72 73 74 75 76 77 78 79 80 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 71 def shutdown wake = @mutex.synchronize do return self if @stopped @stopped = true @heap.clear @wake end wake&.call self end |
#wake_with(&block) ⇒ Object
Installs a lightweight wake callback used when a newly scheduled timer may change EventLoop's current wait deadline.
17 18 19 20 |
# File 'lib/phronomy/engine/runtime/timer_queue.rb', line 17 def wake_with(&block) @mutex.synchronize { @wake = block } self end |