Class: Phronomy::Concurrency::AsyncQueue Private
- Inherits:
-
Object
- Object
- Phronomy::Concurrency::AsyncQueue
- Defined in:
- lib/phronomy/engine/concurrency/async_queue.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
A thread-safe FIFO queue for passing values between concurrent tasks.
Wraps Thread::Queue so that callers do not need to reference the Ruby
standard-library type directly. A future implementation may replace the
backing primitive without changing call sites.
Instance Method Summary collapse
-
#close ⇒ self
private
Closes the queue.
-
#empty? ⇒ Boolean
private
Returns
truewhen the queue contains no items. -
#expect_cross_thread_push(scheduler) ⇒ self
private
Marks this queue as expecting pushes from a non-scheduler OS thread.
-
#initialize(max_size: nil) ⇒ AsyncQueue
constructor
private
A new instance of AsyncQueue.
-
#pop(timeout: nil) ⇒ Object?
private
Dequeues and returns the next item.
-
#push(item) ⇒ self
private
Enqueues
item. -
#size ⇒ Integer
private
Returns the current number of items in the queue.
Constructor Details
#initialize(max_size: nil) ⇒ AsyncQueue
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 AsyncQueue.
20 21 22 23 24 25 26 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 20 def initialize(max_size: nil) @queue = max_size ? SizedQueue.new(max_size) : Thread::Queue.new @max_size = max_size @waiter_mutex = Mutex.new @cross_thread_waiter = nil # [fiber, scheduler] set by _pop_cooperative; consumed by push @cross_thread_scheduler = nil # set by expect_cross_thread_push end |
Instance Method Details
#close ⇒ 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.
Closes the queue. Subsequent #pop calls raise ClosedQueueError.
122 123 124 125 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 122 def close @queue.close self end |
#empty? ⇒ Boolean
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 true when the queue contains no items.
115 116 117 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 115 def empty? @queue.empty? end |
#expect_cross_thread_push(scheduler) ⇒ 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.
Marks this queue as expecting pushes from a non-scheduler OS thread.
When set, #pop in cooperative mode uses track_blocking_await so that
Runtime::DeterministicScheduler#run_until_idle does not exit while
waiting for the cross-thread push. Called by EventLoop#register when
a cooperative scheduler is active on the calling thread.
135 136 137 138 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 135 def expect_cross_thread_push(scheduler) @cross_thread_scheduler = scheduler self end |
#pop(timeout: nil) ⇒ Object?
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.
The :fiber backend is EXPERIMENTAL. Real-time timeout behaviour
in production workloads is not guaranteed and may differ from wall-clock
expectations.
Cooperative timeout limitation: on the cooperative path, the
deadline is re-checked after a wake-up signal arrives. If virtual time
has already passed the deadline when the consumer is woken by a producer
push, the consumer returns nil rather than the pushed item. Without any
wake-up signal the waiting Fiber remains suspended even after
scheduler.advance — the timeout does not self-fire.
Dequeues and returns the next item. In a cooperative scheduler context, suspends the current Fiber (yielding control back to the scheduler) rather than blocking the OS thread.
When timeout is given the semantics depend on the active backend:
- Thread backend (
:thread) — uses real wall-clock time viaThread::Queue#pop(timeout:). Requires Ruby 3.2+. Returnsnilif no item arrives within the specified number of real seconds. - DeterministicScheduler /
:fiberbackend — uses the scheduler's virtual time (+scheduler.virtual_time+). The timeout elapses only when the virtual clock is advanced (e.g. via Testing::FakeClock#advance). In tests this means the timeout is fully deterministic and does not depend on actual elapsed wall time. However, in production:fibermode the timeout may never expire unless the scheduler explicitly advances virtual time.
94 95 96 97 98 99 100 101 102 103 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 94 def pop(timeout: nil) scheduler = Phronomy::Runtime::Scheduler.current if scheduler _pop_cooperative(scheduler, timeout: timeout) elsif timeout @queue.pop(timeout: timeout) else @queue.pop end end |
#push(item) ⇒ 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.
Enqueues item.
In a cooperative scheduler context with a bounded queue (max_size:), suspends
the current Fiber via a scheduler signal when the queue is full rather than
blocking the OS thread. Without a scheduler, falls back to the standard
SizedQueue blocking behaviour.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 36 def push(item) scheduler = Phronomy::Runtime::Scheduler.current if scheduler && @max_size _push_cooperative(scheduler, item) else @queue.push(item) scheduler.raise_signal(@coop_signal) if scheduler && @coop_signal # Wake a cross-thread waiter if one is registered. # Handles the case where a DeterministicScheduler Fiber is suspended # in _pop_cooperative waiting for a push from a non-scheduler thread # (e.g. EventLoop thread where Scheduler.current is nil). # enqueue_fiber is thread-safe; complete_blocking_await decrements # @pending_awaits so run_until_idle can eventually exit. if @cross_thread_scheduler waiter = @waiter_mutex.synchronize do w = @cross_thread_waiter @cross_thread_waiter = nil w end if waiter fiber, sched = waiter sched.complete_blocking_await sched.enqueue_fiber(-> { fiber.resume }) end end end self end |
#size ⇒ Integer
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 the current number of items in the queue.
108 109 110 |
# File 'lib/phronomy/engine/concurrency/async_queue.rb', line 108 def size @queue.size end |