| 25 | |
| 26 | /** @internal */ |
| 27 | export class ResourceRef<A, E = never> { |
| 28 | static from = Effect.fnUntraced(function*<A, E>( |
| 29 | parentScope: Scope.Scope, |
| 30 | acquire: (scope: Scope.Scope) => Effect.Effect<A, E> |
| 31 | ) { |
| 32 | const state = MutableRef.make<State<A, E>>({ _tag: "Closed" }) |
| 33 | |
| 34 | yield* Scope.addFinalizerExit(parentScope, (exit) => { |
| 35 | const s = MutableRef.get(state) |
| 36 | if (s._tag === "Closed") { |
| 37 | return Effect.void |
| 38 | } |
| 39 | const scope = s.scope |
| 40 | MutableRef.set(state, { _tag: "Closed" }) |
| 41 | return Scope.close(scope, exit) |
| 42 | }) |
| 43 | |
| 44 | const scope = yield* Scope.make() |
| 45 | MutableRef.set(state, { _tag: "Acquiring", scope }) |
| 46 | const value = yield* acquire(scope) |
| 47 | MutableRef.set(state, { _tag: "Acquired", scope, value }) |
| 48 | |
| 49 | return new ResourceRef(state, acquire) |
| 50 | }) |
| 51 | |
| 52 | readonly state: MutableRef.MutableRef<State<A, E>> |
| 53 | readonly acquire: (scope: Scope.Scope) => Effect.Effect<A, E> |
| 54 | constructor( |
| 55 | state: MutableRef.MutableRef<State<A, E>>, |
| 56 | acquire: (scope: Scope.Scope) => Effect.Effect<A, E> |
| 57 | ) { |
| 58 | this.state = state |
| 59 | this.acquire = acquire |
| 60 | } |
| 61 | |
| 62 | latch = Latch.makeUnsafe(true) |
| 63 | |
| 64 | getUnsafe(): Option.Option<A> { |
| 65 | if (this.state.current._tag === "Acquired") { |
| 66 | return Option.some(this.state.current.value) |
| 67 | } |
| 68 | return Option.none() |
| 69 | } |
| 70 | |
| 71 | rebuildUnsafe(): Effect.Effect<void, E> { |
| 72 | const s = this.state.current |
| 73 | if (s._tag === "Closed") { |
| 74 | return Effect.interrupt |
| 75 | } |
| 76 | const prevScope = s.scope |
| 77 | const scope = Scope.makeUnsafe() |
| 78 | this.latch.closeUnsafe() |
| 79 | MutableRef.set(this.state, { _tag: "Acquiring", scope }) |
| 80 | return Effect.withFiber((fiber) => { |
| 81 | internalInterruptors.add(fiber.id) |
| 82 | return Scope.close(prevScope, Exit.void) |
| 83 | }).pipe( |
| 84 | Effect.andThen(this.acquire(scope)), |