| 113 | }) |
| 114 | |
| 115 | const ensureRunning = (work: Effect.Effect<A, E>) => |
| 116 | SynchronizedRef.modifyEffect( |
| 117 | ref, |
| 118 | Effect.fnUntraced(function* (st) { |
| 119 | switch (st._tag) { |
| 120 | case "Running": |
| 121 | case "ShellThenRun": |
| 122 | return [awaitDone(st.run.done), st] as const |
| 123 | case "Shell": { |
| 124 | const run = { |
| 125 | id: next(), |
| 126 | done: yield* Deferred.make<A, E | Cancelled>(), |
| 127 | work, |
| 128 | } satisfies PendingHandle<A, E> |
| 129 | return [awaitDone(run.done), { _tag: "ShellThenRun", shell: st.shell, run }] as const |
| 130 | } |
| 131 | case "Idle": { |
| 132 | const done = yield* Deferred.make<A, E | Cancelled>() |
| 133 | const run = yield* startRun(work, done) |
| 134 | return [awaitDone(done), { _tag: "Running", run }] as const |
| 135 | } |
| 136 | } |
| 137 | }), |
| 138 | ).pipe(Effect.flatten) |
| 139 | |
| 140 | const startShell = (work: Effect.Effect<A, E>, ready?: Latch.Latch): Effect.Effect<A, E | Busy> => |
| 141 | SynchronizedRef.modifyEffect( |