Class: Tuile::EventQueue
- Inherits:
-
Object
- Object
- Tuile::EventQueue
- Defined in:
- lib/tuile/event_queue.rb
Overview
An event queue. The idea is that all UI-related updates run from the thread which runs the event queue only; this removes any need for locking and/or need for thread-safety mechanisms.
Any events (keypress, timer, term resize – WINCH) are captured in background threads; instead of processing the events directly the events are pushed into the event queue: this causes the events to be processed centrally, by a single thread only.
Defined Under Namespace
Classes: EmptyQueueEvent, ErrorEvent, KeyEvent, TTYSizeEvent
Instance Method Summary collapse
-
#await_empty ⇒ void
Awaits until the event queue is empty (all events have been processed).
-
#initialize(listen_for_keys: true) ⇒ EventQueue
constructor
A new instance of EventQueue.
-
#locked? ⇒ Boolean
True if this thread is running inside an event queue.
-
#post(event) ⇒ void
Posts event into the event queue.
-
#run_loop {|event| ... } ⇒ void
Runs the event loop and blocks.
-
#stop ⇒ void
Stops ongoing #run_loop.
-
#submit { ... } ⇒ void
Submits block to be run in the event queue.
Constructor Details
#initialize(listen_for_keys: true) ⇒ EventQueue
Returns a new instance of EventQueue.
14 15 16 17 18 |
# File 'lib/tuile/event_queue.rb', line 14 def initialize(listen_for_keys: true) @queue = Thread::Queue.new @listen_for_keys = listen_for_keys @run_lock = Mutex.new end |
Instance Method Details
#await_empty ⇒ void
This method returns an undefined value.
Awaits until the event queue is empty (all events have been processed).
44 45 46 47 48 |
# File 'lib/tuile/event_queue.rb', line 44 def await_empty latch = Concurrent::CountDownLatch.new(1) submit { latch.count_down } latch.wait end |
#locked? ⇒ Boolean
Returns true if this thread is running inside an event queue.
80 |
# File 'lib/tuile/event_queue.rb', line 80 def locked? = @run_lock.owned? |
#post(event) ⇒ void
This method returns an undefined value.
Posts event into the event queue. The event may be of any type. Since the event is passed between threads, the event object should be frozen.
The function may be called from any thread.
26 27 28 29 30 |
# File 'lib/tuile/event_queue.rb', line 26 def post(event) raise ArgumentError, "event passed across threads must be frozen, got #{event.inspect}" unless event.frozen? @queue << event end |
#run_loop {|event| ... } ⇒ void
This method returns an undefined value.
Runs the event loop and blocks. Must be run from at most one thread at the same time. Blocks until some thread calls #stop. Calls block for all events submitted via #post; the block is always called from the thread running this function.
Any exception raised by block is re-thrown, causing this function to terminate.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/tuile/event_queue.rb', line 63 def run_loop(&) raise ArgumentError, "run_loop requires a block" unless block_given? @run_lock.synchronize do start_key_thread if @listen_for_keys begin trap_winch event_loop(&) ensure Signal.trap("WINCH", "SYSTEM_DEFAULT") @key_thread&.kill @queue.clear end end end |
#stop ⇒ void
88 89 90 91 |
# File 'lib/tuile/event_queue.rb', line 88 def stop @queue.clear post(nil) end |
#submit { ... } ⇒ void
This method returns an undefined value.
Submits block to be run in the event queue. Returns immediately.
The function may be called from any thread.
38 39 40 |
# File 'lib/tuile/event_queue.rb', line 38 def submit(&block) @queue << block end |