(work: Effect.Effect<A, E>, ready?: Latch.Latch)
| 138 | ).pipe(Effect.flatten) |
| 139 | |
| 140 | const startShell = (work: Effect.Effect<A, E>, ready?: Latch.Latch): Effect.Effect<A, E | Busy> => |
| 141 | SynchronizedRef.modifyEffect( |
| 142 | ref, |
| 143 | Effect.fnUntraced(function* (st) { |
| 144 | if (st._tag !== "Idle") { |
| 145 | const reject: Effect.Effect<A, E | Busy> = Effect.fail(new Busy()) |
| 146 | return [reject, st] as const |
| 147 | } |
| 148 | yield* onBusy |
| 149 | const id = next() |
| 150 | const cancelled = yield* Deferred.make<void>() |
| 151 | const fiber = yield* work.pipe(Effect.ensuring(finishShell(id)), Effect.forkChild) |
| 152 | const shell = { id, cancelled, ready, fiber } satisfies ShellHandle<A, E> |
| 153 | return [ |
| 154 | Effect.gen(function* () { |
| 155 | const exit = yield* Fiber.await(fiber) |
| 156 | if (Exit.isSuccess(exit)) return exit.value |
| 157 | if ( |
| 158 | Cause.hasInterruptsOnly(exit.cause) || |
| 159 | ((yield* Deferred.isDone(cancelled)) && Cause.hasInterrupts(exit.cause) && !Cause.hasDies(exit.cause)) |
| 160 | ) { |
| 161 | if (onInterrupt) return yield* onInterrupt |
| 162 | return yield* Effect.die(new Cancelled()) |
| 163 | } |
| 164 | return yield* Effect.failCause(exit.cause) |
| 165 | }), |
| 166 | { _tag: "Shell", shell }, |
| 167 | ] as const |
| 168 | }), |
| 169 | ).pipe(Effect.flatten) |
| 170 | |
| 171 | const cancel = SynchronizedRef.modify(ref, (st) => { |
| 172 | switch (st._tag) { |
nothing calls this directly
no test coverage detected