Class: Charming::Internal::EventLoop
- Inherits:
-
Object
- Object
- Charming::Internal::EventLoop
- Defined in:
- lib/charming/internal/event_loop.rb
Overview
EventLoop pumps events for a Charming runtime: it delivers the next due event — completed background tasks first, then due timers, then terminal input (with optional held-key coalescing) — to the block passed to #run, until the block returns :quit, the interrupt check trips, or a test backend runs out of events. It knows nothing about controllers, routes, or rendering; deciding what an event means belongs to its caller.
Constant Summary collapse
- DEFAULT_READ_TIMEOUT =
0.05
Instance Method Summary collapse
-
#initialize(backend:, clock:, task_queue:, timer_bindings: [], coalesce_input: false, interrupted: -> { false }) ⇒ EventLoop
constructor
timer_bindings is the list of controller timer bindings (each responding to
nameandinterval) to schedule. -
#reset_timers(timer_bindings) ⇒ Object
Replaces the scheduled timers — called when navigation lands on a controller with different timer bindings.
-
#run ⇒ Object
Pumps events, yielding each to the caller together with a flag saying whether another event is already due (letting the caller coalesce a burst into one repaint).
-
#start_timer(binding) ⇒ Object
Schedules binding one interval from now.
-
#stop_timer(name) ⇒ Object
Removes the named timer from the schedule.
-
#timer_running?(name) ⇒ Boolean
True while the named timer is scheduled.
Constructor Details
#initialize(backend:, clock:, task_queue:, timer_bindings: [], coalesce_input: false, interrupted: -> { false }) ⇒ EventLoop
timer_bindings is the list of controller timer bindings (each
responding to name and interval) to schedule. interrupted is a
callable checked every iteration so a signal handler can stop the loop.
17 18 19 20 21 22 23 24 25 |
# File 'lib/charming/internal/event_loop.rb', line 17 def initialize(backend:, clock:, task_queue:, timer_bindings: [], coalesce_input: false, interrupted: -> { false }) @backend = backend @clock = clock @task_queue = task_queue @coalesce_input = coalesce_input @interrupted = interrupted @timers = build_timers(timer_bindings) @pending_event = nil end |
Instance Method Details
#reset_timers(timer_bindings) ⇒ Object
Replaces the scheduled timers — called when navigation lands on a controller with different timer bindings.
50 51 52 |
# File 'lib/charming/internal/event_loop.rb', line 50 def reset_timers(timer_bindings) @timers = build_timers(timer_bindings) end |
#run ⇒ Object
Pumps events, yielding each to the caller together with a flag saying whether another event is already due (letting the caller coalesce a burst into one repaint). Stops when the block returns :quit, when the interrupt check returns true, or when a test backend is exhausted. Closes the task queue on the way out so producer threads can't block on a loop that is no longer draining them.
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/charming/internal/event_loop.rb', line 33 def run loop do break if @interrupted.call event = next_event unless event break if backend_exhausted? next end break if yield(event, more_ready?) == :quit end ensure @task_queue.close end |
#start_timer(binding) ⇒ Object
Schedules binding one interval from now. Idempotent: starting a timer that is already running keeps its current deadline (no phase reset).
56 57 58 59 60 |
# File 'lib/charming/internal/event_loop.rb', line 56 def start_timer(binding) return if timer_running?(binding.name) @timers << {binding: binding, next_at: clock_now + binding.interval} end |
#stop_timer(name) ⇒ Object
Removes the named timer from the schedule. Idempotent for unknown names.
63 64 65 |
# File 'lib/charming/internal/event_loop.rb', line 63 def stop_timer(name) @timers.reject! { |timer| timer.fetch(:binding).name == name } end |
#timer_running?(name) ⇒ Boolean
True while the named timer is scheduled.
68 69 70 |
# File 'lib/charming/internal/event_loop.rb', line 68 def timer_running?(name) @timers.any? { |timer| timer.fetch(:binding).name == name } end |