Class: Phronomy::Task::FiberBackend Private
- Defined in:
- lib/phronomy/task/fiber_backend.rb
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.
Instance Method Summary collapse
-
#alive? ⇒ Boolean
private
+true+ while the Fiber has not yet finished.
-
#await ⇒ Object
private
Blocks until the task completes.
-
#cancel! ⇒ self
private
Requests cancellation using a cooperative checkpoint mechanism.
-
#cooperative_suspend? ⇒ Boolean
private
Returns +true+ if the Fiber yielded cooperatively (via a signal wait) and should not be automatically re-enqueued by the scheduler.
-
#initialize(task:, &block) ⇒ FiberBackend
constructor
private
A new instance of FiberBackend.
-
#join(_limit = nil) ⇒ self
private
Joins execution by stepping until the Fiber is no longer alive.
-
#step ⇒ self
private
Advances execution by one scheduler step.
Methods inherited from Backend
#completed_error, #completed_value
Constructor Details
#initialize(task:, &block) ⇒ FiberBackend
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 FiberBackend.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/phronomy/task/fiber_backend.rb', line 22 def initialize(task:, &block) super @value = nil @error = nil @cancel_error = nil @cancel_requested = false @started = false @cooperative_suspend = false # Capture `self` (the FiberBackend instance) in the closure so that # instance-variable writes from inside the Fiber update this object. @fiber = Fiber.new do task.transition!(:running) begin # If cancel! was called before the first step, raise immediately. raise @cancel_error if @cancel_error @value = block.call task.transition!(:completed, value: @value) rescue CancellationError => e task.transition!(:cancelled, error: e) @error = e rescue => e task.transition!(:failed, error: e) @error = e ensure task.transition!(:cancelled) unless task.done? end end end |
Instance Method Details
#alive? ⇒ 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+ while the Fiber has not yet finished.
129 130 131 |
# File 'lib/phronomy/task/fiber_backend.rb', line 129 def alive? @fiber.alive? end |
#await ⇒ 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.
Blocks until the task completes.
When called from within a DeterministicScheduler-managed Fiber, suspends the current Fiber cooperatively and schedules it to resume when this task completes. When called from outside a managed Fiber (e.g. the main fiber or a regular thread), drives execution by calling #step in a loop.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/phronomy/task/fiber_backend.rb', line 103 def await unless @fiber.alive? raise @error if @error return @value end scheduler = Thread.current.thread_variable_get(SCHEDULER_KEY) # Fiber.main was added in Ruby 3.2.4+; fall back to true (assume we are # inside a managed Fiber whenever a scheduler is active). in_managed_fiber = !Fiber.respond_to?(:main) || Fiber.current != Fiber.main if scheduler && in_managed_fiber # Cooperative context: suspend current Fiber until task is done. waiting_fiber = Fiber.current @task.on_complete { scheduler.enqueue_fiber(-> { waiting_fiber.resume }) } Fiber.yield(:cooperative_suspend) else # Non-cooperative context: drive the fiber to completion. step while @fiber.alive? end raise @error if @error @value end |
#cancel! ⇒ 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.
Requests cancellation using a cooperative checkpoint mechanism. Sets a cancellation flag; the error is raised inside the Fiber at the next +step+ call (i.e. when the scheduler next dispatches this task), not injected at an arbitrary suspension point via +Fiber#raise+. If the Fiber has not yet started, the error is recorded so it is raised on the first #step.
141 142 143 144 145 |
# File 'lib/phronomy/task/fiber_backend.rb', line 141 def cancel! @cancel_error = CancellationError.new("Task cancelled") @cancel_requested = true self end |
#cooperative_suspend? ⇒ 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+ if the Fiber yielded cooperatively (via a signal wait) and should not be automatically re-enqueued by the scheduler.
88 89 90 |
# File 'lib/phronomy/task/fiber_backend.rb', line 88 def cooperative_suspend? @cooperative_suspend end |
#join(_limit = nil) ⇒ 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.
Joins execution by stepping until the Fiber is no longer alive.
151 152 153 154 |
# File 'lib/phronomy/task/fiber_backend.rb', line 151 def join(_limit = nil) step while @fiber.alive? self end |
#step ⇒ 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.
Advances execution by one scheduler step. Resumes the Fiber until it yields (via +Fiber.yield+) or finishes. Cooperative cancellation is checked at the start of each step: if +cancel!+ has been called, +CancellationError+ is raised inside the Fiber at this controlled checkpoint rather than injected at an arbitrary suspension point via +Fiber#raise+.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/phronomy/task/fiber_backend.rb', line 61 def step return self unless @fiber.alive? @started = true # Deliver pending cancellation at this scheduler checkpoint rather than # injecting it mid-Fiber via Fiber#raise (which would be preemptive). if @cancel_requested && @cancel_error begin @fiber.raise(@cancel_error) rescue FiberError nil # Fiber completed between the check and raise — safe to ignore. end @cancel_requested = false return self end yield_value = @fiber.resume # A yield value of :cooperative_suspend signals that the Fiber deliberately # suspended itself (e.g. inside CoopSignal#wait) and must NOT be # re-enqueued by step_callable — it will be resumed by an explicit signal. @cooperative_suspend = (yield_value == :cooperative_suspend) self end |