Class: Dommy::Scheduler
- Inherits:
-
Object
- Object
- Dommy::Scheduler
- Defined in:
- lib/dommy/scheduler.rb
Overview
Deterministic host-side scheduler for timers, rAF, and microtasks. Time advances only when the host explicitly calls ‘advance_time`.
Defined Under Namespace
Classes: Timer
Constant Summary collapse
- FRAME_MS =
16
Instance Attribute Summary collapse
-
#now_ms ⇒ Object
readonly
Returns the value of attribute now_ms.
Instance Method Summary collapse
- #advance_time(delta_ms) ⇒ Object
- #cancel_animation_frame(id) ⇒ Object
- #clear_interval(id) ⇒ Object
- #clear_timeout(id) ⇒ Object
- #drain_microtasks ⇒ Object
- #drain_timers(advance: 0) ⇒ Object
-
#initialize ⇒ Scheduler
constructor
A new instance of Scheduler.
-
#next_due_timer_at ⇒ Object
Public accessor for eval-time auto-drain: keep advancing the clock until no timers remain (or a safety budget runs out).
- #queue_microtask(callback) ⇒ Object
- #request_animation_frame(callback) ⇒ Object
- #set_interval(callback, interval_ms) ⇒ Object
- #set_timeout(callback, delay_ms) ⇒ Object
Constructor Details
#initialize ⇒ Scheduler
Returns a new instance of Scheduler.
11 12 13 14 15 16 |
# File 'lib/dommy/scheduler.rb', line 11 def initialize @now_ms = 0 @next_id = 1 @timers = {} @microtasks = [] end |
Instance Attribute Details
#now_ms ⇒ Object (readonly)
Returns the value of attribute now_ms.
18 19 20 |
# File 'lib/dommy/scheduler.rb', line 18 def now_ms @now_ms end |
Instance Method Details
#advance_time(delta_ms) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/dommy/scheduler.rb', line 62 def advance_time(delta_ms) target = @now_ms + [delta_ms.to_i, 0].max while next_due_timer_at && next_due_timer_at <= target @now_ms = next_due_timer_at run_due_timers drain_microtasks end @now_ms = target drain_microtasks nil end |
#cancel_animation_frame(id) ⇒ Object
44 45 46 |
# File 'lib/dommy/scheduler.rb', line 44 def cancel_animation_frame(id) cancel_timer(id) end |
#clear_interval(id) ⇒ Object
33 34 35 |
# File 'lib/dommy/scheduler.rb', line 33 def clear_interval(id) cancel_timer(id) end |
#clear_timeout(id) ⇒ Object
24 25 26 |
# File 'lib/dommy/scheduler.rb', line 24 def clear_timeout(id) cancel_timer(id) end |
#drain_microtasks ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/dommy/scheduler.rb', line 53 def drain_microtasks until @microtasks.empty? callback = @microtasks.shift invoke_callback(callback, [@now_ms]) end nil end |
#drain_timers(advance: 0) ⇒ Object
75 76 77 |
# File 'lib/dommy/scheduler.rb', line 75 def drain_timers(advance: 0) advance_time(advance) end |
#next_due_timer_at ⇒ Object
Public accessor for eval-time auto-drain: keep advancing the clock until no timers remain (or a safety budget runs out).
81 82 83 |
# File 'lib/dommy/scheduler.rb', line 81 def next_due_timer_at @timers.values.select(&:active).map(&:due_at).min end |
#queue_microtask(callback) ⇒ Object
48 49 50 51 |
# File 'lib/dommy/scheduler.rb', line 48 def queue_microtask(callback) @microtasks << callback nil end |
#request_animation_frame(callback) ⇒ Object
37 38 39 40 41 42 |
# File 'lib/dommy/scheduler.rb', line 37 def request_animation_frame(callback) frames = ((@now_ms / FRAME_MS) + 1) * FRAME_MS id = next_id @timers[id] = Timer.new(id, :raf, callback, frames, nil, true) id end |
#set_interval(callback, interval_ms) ⇒ Object
28 29 30 31 |
# File 'lib/dommy/scheduler.rb', line 28 def set_interval(callback, interval_ms) ms = [interval_ms.to_i, 0].max register_timer(:interval, callback, ms, ms) end |
#set_timeout(callback, delay_ms) ⇒ Object
20 21 22 |
# File 'lib/dommy/scheduler.rb', line 20 def set_timeout(callback, delay_ms) register_timer(:timeout, callback, delay_ms.to_i, nil) end |