effect 3.4.9 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/RcMap/package.json +6 -0
  2. package/RcRef/package.json +6 -0
  3. package/dist/cjs/Cause.js +22 -1
  4. package/dist/cjs/Cause.js.map +1 -1
  5. package/dist/cjs/Channel.js.map +1 -1
  6. package/dist/cjs/Config.js.map +1 -1
  7. package/dist/cjs/Console.js.map +1 -1
  8. package/dist/cjs/Data.js +3 -1
  9. package/dist/cjs/Data.js.map +1 -1
  10. package/dist/cjs/Duration.js +23 -2
  11. package/dist/cjs/Duration.js.map +1 -1
  12. package/dist/cjs/Logger.js +11 -1
  13. package/dist/cjs/Logger.js.map +1 -1
  14. package/dist/cjs/PubSub.js.map +1 -1
  15. package/dist/cjs/Random.js +9 -1
  16. package/dist/cjs/Random.js.map +1 -1
  17. package/dist/cjs/RcMap.js +52 -0
  18. package/dist/cjs/RcMap.js.map +1 -0
  19. package/dist/cjs/RcRef.js +51 -0
  20. package/dist/cjs/RcRef.js.map +1 -0
  21. package/dist/cjs/Stream.js +29 -2
  22. package/dist/cjs/Stream.js.map +1 -1
  23. package/dist/cjs/index.js +6 -2
  24. package/dist/cjs/index.js.map +1 -1
  25. package/dist/cjs/internal/cause.js +21 -5
  26. package/dist/cjs/internal/cause.js.map +1 -1
  27. package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
  28. package/dist/cjs/internal/channel.js.map +1 -1
  29. package/dist/cjs/internal/core-effect.js +0 -5
  30. package/dist/cjs/internal/core-effect.js.map +1 -1
  31. package/dist/cjs/internal/core.js +15 -10
  32. package/dist/cjs/internal/core.js.map +1 -1
  33. package/dist/cjs/internal/defaultServices.js +1 -1
  34. package/dist/cjs/internal/defaultServices.js.map +1 -1
  35. package/dist/cjs/internal/fiberRuntime.js +3 -1
  36. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  37. package/dist/cjs/internal/logger.js +128 -27
  38. package/dist/cjs/internal/logger.js.map +1 -1
  39. package/dist/cjs/internal/pubsub.js +216 -36
  40. package/dist/cjs/internal/pubsub.js.map +1 -1
  41. package/dist/cjs/internal/random.js +2 -1
  42. package/dist/cjs/internal/random.js.map +1 -1
  43. package/dist/cjs/internal/rcMap.js +129 -0
  44. package/dist/cjs/internal/rcMap.js.map +1 -0
  45. package/dist/cjs/internal/rcRef.js +122 -0
  46. package/dist/cjs/internal/rcRef.js.map +1 -0
  47. package/dist/cjs/internal/stream.js +57 -11
  48. package/dist/cjs/internal/stream.js.map +1 -1
  49. package/dist/cjs/internal/version.js +1 -1
  50. package/dist/dts/Cause.d.ts +40 -1
  51. package/dist/dts/Cause.d.ts.map +1 -1
  52. package/dist/dts/Channel.d.ts +3 -3
  53. package/dist/dts/Channel.d.ts.map +1 -1
  54. package/dist/dts/Config.d.ts +5 -0
  55. package/dist/dts/Config.d.ts.map +1 -1
  56. package/dist/dts/Console.d.ts +2 -4
  57. package/dist/dts/Console.d.ts.map +1 -1
  58. package/dist/dts/Duration.d.ts +5 -0
  59. package/dist/dts/Duration.d.ts.map +1 -1
  60. package/dist/dts/Logger.d.ts +15 -0
  61. package/dist/dts/Logger.d.ts.map +1 -1
  62. package/dist/dts/PubSub.d.ts +15 -4
  63. package/dist/dts/PubSub.d.ts.map +1 -1
  64. package/dist/dts/Random.d.ts +8 -0
  65. package/dist/dts/Random.d.ts.map +1 -1
  66. package/dist/dts/RcMap.d.ts +93 -0
  67. package/dist/dts/RcMap.d.ts.map +1 -0
  68. package/dist/dts/RcRef.d.ts +83 -0
  69. package/dist/dts/RcRef.d.ts.map +1 -0
  70. package/dist/dts/Stream.d.ts +64 -26
  71. package/dist/dts/Stream.d.ts.map +1 -1
  72. package/dist/dts/index.d.ts +8 -0
  73. package/dist/dts/index.d.ts.map +1 -1
  74. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  75. package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
  76. package/dist/dts/internal/logger.d.ts.map +1 -1
  77. package/dist/dts/internal/random.d.ts +1 -1
  78. package/dist/dts/internal/random.d.ts.map +1 -1
  79. package/dist/dts/internal/rcMap.d.ts +2 -0
  80. package/dist/dts/internal/rcMap.d.ts.map +1 -0
  81. package/dist/dts/internal/rcRef.d.ts +2 -0
  82. package/dist/dts/internal/rcRef.d.ts.map +1 -0
  83. package/dist/dts/internal/stream.d.ts +1 -0
  84. package/dist/dts/internal/stream.d.ts.map +1 -1
  85. package/dist/esm/Cause.js +21 -0
  86. package/dist/esm/Cause.js.map +1 -1
  87. package/dist/esm/Channel.js.map +1 -1
  88. package/dist/esm/Config.js.map +1 -1
  89. package/dist/esm/Console.js.map +1 -1
  90. package/dist/esm/Data.js +3 -1
  91. package/dist/esm/Data.js.map +1 -1
  92. package/dist/esm/Duration.js +20 -0
  93. package/dist/esm/Duration.js.map +1 -1
  94. package/dist/esm/Logger.js +10 -0
  95. package/dist/esm/Logger.js.map +1 -1
  96. package/dist/esm/PubSub.js.map +1 -1
  97. package/dist/esm/Random.js +8 -0
  98. package/dist/esm/Random.js.map +1 -1
  99. package/dist/esm/RcMap.js +44 -0
  100. package/dist/esm/RcMap.js.map +1 -0
  101. package/dist/esm/RcRef.js +43 -0
  102. package/dist/esm/RcRef.js.map +1 -0
  103. package/dist/esm/Stream.js +27 -0
  104. package/dist/esm/Stream.js.map +1 -1
  105. package/dist/esm/index.js +8 -0
  106. package/dist/esm/index.js.map +1 -1
  107. package/dist/esm/internal/cause.js +21 -5
  108. package/dist/esm/internal/cause.js.map +1 -1
  109. package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
  110. package/dist/esm/internal/channel.js.map +1 -1
  111. package/dist/esm/internal/core-effect.js +0 -5
  112. package/dist/esm/internal/core-effect.js.map +1 -1
  113. package/dist/esm/internal/core.js +11 -7
  114. package/dist/esm/internal/core.js.map +1 -1
  115. package/dist/esm/internal/defaultServices.js +1 -1
  116. package/dist/esm/internal/defaultServices.js.map +1 -1
  117. package/dist/esm/internal/fiberRuntime.js +2 -0
  118. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  119. package/dist/esm/internal/logger.js +126 -26
  120. package/dist/esm/internal/logger.js.map +1 -1
  121. package/dist/esm/internal/pubsub.js +216 -36
  122. package/dist/esm/internal/pubsub.js.map +1 -1
  123. package/dist/esm/internal/random.js +2 -1
  124. package/dist/esm/internal/random.js.map +1 -1
  125. package/dist/esm/internal/rcMap.js +120 -0
  126. package/dist/esm/internal/rcMap.js.map +1 -0
  127. package/dist/esm/internal/rcRef.js +112 -0
  128. package/dist/esm/internal/rcRef.js.map +1 -0
  129. package/dist/esm/internal/stream.js +53 -8
  130. package/dist/esm/internal/stream.js.map +1 -1
  131. package/dist/esm/internal/version.js +1 -1
  132. package/package.json +17 -1
  133. package/src/Cause.ts +47 -1
  134. package/src/Channel.ts +3 -3
  135. package/src/Config.ts +6 -0
  136. package/src/Console.ts +2 -4
  137. package/src/Data.ts +1 -1
  138. package/src/Duration.ts +18 -0
  139. package/src/Logger.ts +19 -0
  140. package/src/PubSub.ts +11 -4
  141. package/src/Random.ts +9 -0
  142. package/src/RcMap.ts +103 -0
  143. package/src/RcRef.ts +91 -0
  144. package/src/Stream.ts +83 -26
  145. package/src/index.ts +10 -0
  146. package/src/internal/cause.ts +26 -5
  147. package/src/internal/channel/channelExecutor.ts +1 -1
  148. package/src/internal/channel.ts +4 -3
  149. package/src/internal/core-effect.ts +0 -5
  150. package/src/internal/core.ts +19 -9
  151. package/src/internal/defaultServices.ts +1 -1
  152. package/src/internal/fiberRuntime.ts +6 -0
  153. package/src/internal/logger.ts +133 -27
  154. package/src/internal/pubsub.ts +249 -58
  155. package/src/internal/random.ts +2 -1
  156. package/src/internal/rcMap.ts +213 -0
  157. package/src/internal/rcRef.ts +172 -0
  158. package/src/internal/stream.ts +325 -111
  159. package/src/internal/version.ts +1 -1
@@ -0,0 +1,213 @@
1
+ import type * as Cause from "../Cause.js"
2
+ import * as Context from "../Context.js"
3
+ import type * as Deferred from "../Deferred.js"
4
+ import * as Duration from "../Duration.js"
5
+ import type { Effect } from "../Effect.js"
6
+ import type { RuntimeFiber } from "../Fiber.js"
7
+ import { dual, identity } from "../Function.js"
8
+ import * as MutableHashMap from "../MutableHashMap.js"
9
+ import { pipeArguments } from "../Pipeable.js"
10
+ import type * as RcMap from "../RcMap.js"
11
+ import type * as Scope from "../Scope.js"
12
+ import * as coreEffect from "./core-effect.js"
13
+ import * as core from "./core.js"
14
+ import * as circular from "./effect/circular.js"
15
+ import * as fiberRuntime from "./fiberRuntime.js"
16
+
17
+ /** @internal */
18
+ export const TypeId: RcMap.TypeId = Symbol.for("effect/RcMap") as RcMap.TypeId
19
+
20
+ type State<K, A, E> = State.Open<K, A, E> | State.Closed
21
+
22
+ declare namespace State {
23
+ interface Open<K, A, E> {
24
+ readonly _tag: "Open"
25
+ readonly map: MutableHashMap.MutableHashMap<K, Entry<A, E>>
26
+ }
27
+
28
+ interface Closed {
29
+ readonly _tag: "Closed"
30
+ }
31
+
32
+ interface Entry<A, E> {
33
+ readonly deferred: Deferred.Deferred<A, E>
34
+ readonly scope: Scope.CloseableScope
35
+ fiber: RuntimeFiber<void, never> | undefined
36
+ refCount: number
37
+ }
38
+ }
39
+
40
+ const variance: RcMap.RcMap.Variance<any, any, any> = {
41
+ _K: identity,
42
+ _A: identity,
43
+ _E: identity
44
+ }
45
+
46
+ class RcMapImpl<K, A, E> implements RcMap.RcMap<K, A, E> {
47
+ readonly [TypeId]: RcMap.RcMap.Variance<K, A, E>
48
+
49
+ state: State<K, A, E> = {
50
+ _tag: "Open",
51
+ map: MutableHashMap.empty()
52
+ }
53
+ readonly semaphore = circular.unsafeMakeSemaphore(1)
54
+
55
+ constructor(
56
+ readonly lookup: (key: K) => Effect<A, E, Scope.Scope>,
57
+ readonly context: Context.Context<never>,
58
+ readonly scope: Scope.Scope,
59
+ readonly idleTimeToLive: Duration.Duration | undefined,
60
+ readonly capacity: number
61
+ ) {
62
+ this[TypeId] = variance
63
+ }
64
+
65
+ pipe() {
66
+ return pipeArguments(this, arguments)
67
+ }
68
+ }
69
+
70
+ /** @internal */
71
+ export const make: {
72
+ <K, A, E, R>(options: {
73
+ readonly lookup: (key: K) => Effect<A, E, R>
74
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
75
+ readonly capacity?: undefined
76
+ }): Effect<RcMap.RcMap<K, A, E>, never, Scope.Scope | R>
77
+ <K, A, E, R>(options: {
78
+ readonly lookup: (key: K) => Effect<A, E, R>
79
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
80
+ readonly capacity: number
81
+ }): Effect<RcMap.RcMap<K, A, E | Cause.ExceededCapacityException>, never, Scope.Scope | R>
82
+ } = <K, A, E, R>(options: {
83
+ readonly lookup: (key: K) => Effect<A, E, R>
84
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
85
+ readonly capacity?: number | undefined
86
+ }) =>
87
+ core.withFiberRuntime<RcMap.RcMap<K, A, E>, never, R | Scope.Scope>((fiber) => {
88
+ const context = fiber.getFiberRef(core.currentContext) as Context.Context<R | Scope.Scope>
89
+ const scope = Context.get(context, fiberRuntime.scopeTag)
90
+ const self = new RcMapImpl<K, A, E>(
91
+ options.lookup as any,
92
+ context,
93
+ scope,
94
+ options.idleTimeToLive ? Duration.decode(options.idleTimeToLive) : undefined,
95
+ Math.max(options.capacity ?? Number.POSITIVE_INFINITY, 0)
96
+ )
97
+ return core.as(
98
+ scope.addFinalizer(() =>
99
+ core.suspend(() => {
100
+ if (self.state._tag === "Closed") {
101
+ return core.void
102
+ }
103
+ const map = self.state.map
104
+ self.state = { _tag: "Closed" }
105
+ return core.forEachSequentialDiscard(
106
+ map,
107
+ ([, entry]) => core.scopeClose(entry.scope, core.exitVoid)
108
+ ).pipe(
109
+ core.tap(() => {
110
+ MutableHashMap.clear(map)
111
+ }),
112
+ self.semaphore.withPermits(1)
113
+ )
114
+ })
115
+ ),
116
+ self
117
+ )
118
+ })
119
+
120
+ /** @internal */
121
+ export const get: {
122
+ <K>(key: K): <A, E>(self: RcMap.RcMap<K, A, E>) => Effect<A, E, Scope.Scope>
123
+ <K, A, E>(self: RcMap.RcMap<K, A, E>, key: K): Effect<A, E, Scope.Scope>
124
+ } = dual(
125
+ 2,
126
+ <K, A, E>(self_: RcMap.RcMap<K, A, E>, key: K): Effect<A, E, Scope.Scope> => {
127
+ const self = self_ as RcMapImpl<K, A, E>
128
+ return core.uninterruptibleMask((restore) =>
129
+ core.suspend(() => {
130
+ if (self.state._tag === "Closed") {
131
+ return core.interrupt
132
+ }
133
+ const state = self.state
134
+ const o = MutableHashMap.get(state.map, key)
135
+ if (o._tag === "Some") {
136
+ const entry = o.value
137
+ entry.refCount++
138
+ return entry.fiber
139
+ ? core.as(core.interruptFiber(entry.fiber), entry)
140
+ : core.succeed(entry)
141
+ } else if (Number.isFinite(self.capacity) && MutableHashMap.size(self.state.map) >= self.capacity) {
142
+ return core.fail(
143
+ new core.ExceededCapacityException(`RcMap attempted to exceed capacity of ${self.capacity}`)
144
+ ) as Effect<never>
145
+ }
146
+ const acquire = self.lookup(key)
147
+ return fiberRuntime.scopeMake().pipe(
148
+ coreEffect.bindTo("scope"),
149
+ coreEffect.bind("deferred", () => core.deferredMake<A, E>()),
150
+ core.tap(({ deferred, scope }) =>
151
+ restore(core.fiberRefLocally(
152
+ acquire as Effect<A, E>,
153
+ core.currentContext,
154
+ Context.add(self.context, fiberRuntime.scopeTag, scope)
155
+ )).pipe(
156
+ core.exit,
157
+ core.flatMap((exit) => core.deferredDone(deferred, exit)),
158
+ circular.forkIn(scope)
159
+ )
160
+ ),
161
+ core.map(({ deferred, scope }) => {
162
+ const entry: State.Entry<A, E> = {
163
+ deferred,
164
+ scope,
165
+ fiber: undefined,
166
+ refCount: 1
167
+ }
168
+ MutableHashMap.set(state.map, key, entry)
169
+ return entry
170
+ })
171
+ )
172
+ }).pipe(
173
+ self.semaphore.withPermits(1),
174
+ coreEffect.bindTo("entry"),
175
+ coreEffect.bind("scope", () => fiberRuntime.scopeTag),
176
+ core.tap(({ entry, scope }) =>
177
+ scope.addFinalizer(() =>
178
+ core.suspend(() => {
179
+ entry.refCount--
180
+ if (entry.refCount > 0) {
181
+ return core.void
182
+ } else if (self.idleTimeToLive === undefined) {
183
+ if (self.state._tag === "Open") {
184
+ MutableHashMap.remove(self.state.map, key)
185
+ }
186
+ return core.scopeClose(entry.scope, core.exitVoid)
187
+ }
188
+ return coreEffect.sleep(self.idleTimeToLive).pipe(
189
+ core.interruptible,
190
+ core.zipRight(core.suspend(() => {
191
+ if (self.state._tag === "Open" && entry.refCount === 0) {
192
+ MutableHashMap.remove(self.state.map, key)
193
+ return core.scopeClose(entry.scope, core.exitVoid)
194
+ }
195
+ return core.void
196
+ })),
197
+ fiberRuntime.ensuring(core.sync(() => {
198
+ entry.fiber = undefined
199
+ })),
200
+ circular.forkIn(self.scope),
201
+ core.tap((fiber) => {
202
+ entry.fiber = fiber
203
+ }),
204
+ self.semaphore.withPermits(1)
205
+ )
206
+ })
207
+ )
208
+ ),
209
+ core.flatMap(({ entry }) => restore(core.deferredAwait(entry.deferred)))
210
+ )
211
+ )
212
+ }
213
+ )
@@ -0,0 +1,172 @@
1
+ import * as Context from "../Context.js"
2
+ import * as Duration from "../Duration.js"
3
+ import type { Effect } from "../Effect.js"
4
+ import type { RuntimeFiber } from "../Fiber.js"
5
+ import { identity } from "../Function.js"
6
+ import { pipeArguments } from "../Pipeable.js"
7
+ import type * as RcRef from "../RcRef.js"
8
+ import type * as Scope from "../Scope.js"
9
+ import * as coreEffect from "./core-effect.js"
10
+ import * as core from "./core.js"
11
+ import * as circular from "./effect/circular.js"
12
+ import * as fiberRuntime from "./fiberRuntime.js"
13
+
14
+ /** @internal */
15
+ export const TypeId: RcRef.TypeId = Symbol.for("effect/RcRef") as RcRef.TypeId
16
+
17
+ type State<A> = State.Empty | State.Acquired<A> | State.Closed
18
+
19
+ declare namespace State {
20
+ interface Empty {
21
+ readonly _tag: "Empty"
22
+ }
23
+
24
+ interface Acquired<A> {
25
+ readonly _tag: "Acquired"
26
+ readonly value: A
27
+ readonly scope: Scope.CloseableScope
28
+ fiber: RuntimeFiber<void, never> | undefined
29
+ refCount: number
30
+ }
31
+
32
+ interface Closed {
33
+ readonly _tag: "Closed"
34
+ }
35
+ }
36
+
37
+ const stateEmpty: State<never> = { _tag: "Empty" }
38
+ const stateClosed: State<never> = { _tag: "Closed" }
39
+
40
+ const variance: RcRef.RcRef.Variance<any, any> = {
41
+ _A: identity,
42
+ _E: identity
43
+ }
44
+
45
+ class RcRefImpl<A, E> implements RcRef.RcRef<A, E> {
46
+ readonly [TypeId]: RcRef.RcRef.Variance<A, E>
47
+
48
+ state: State<A> = stateEmpty
49
+ readonly semaphore = circular.unsafeMakeSemaphore(1)
50
+
51
+ constructor(
52
+ readonly acquire: Effect<A, E, Scope.Scope>,
53
+ readonly context: Context.Context<never>,
54
+ readonly scope: Scope.Scope,
55
+ readonly idleTimeToLive: Duration.Duration | undefined
56
+ ) {
57
+ this[TypeId] = variance
58
+ }
59
+
60
+ pipe() {
61
+ return pipeArguments(this, arguments)
62
+ }
63
+ }
64
+
65
+ /** @internal */
66
+ export const make = <A, E, R>(options: {
67
+ readonly acquire: Effect<A, E, R>
68
+ readonly idleTimeToLive?: Duration.DurationInput | undefined
69
+ }) =>
70
+ core.withFiberRuntime<RcRef.RcRef<A, E>, never, R | Scope.Scope>((fiber) => {
71
+ const context = fiber.getFiberRef(core.currentContext) as Context.Context<R | Scope.Scope>
72
+ const scope = Context.get(context, fiberRuntime.scopeTag)
73
+ const ref = new RcRefImpl<A, E>(
74
+ options.acquire as Effect<A, E, Scope.Scope>,
75
+ context,
76
+ scope,
77
+ options.idleTimeToLive ? Duration.decode(options.idleTimeToLive) : undefined
78
+ )
79
+ return core.as(
80
+ scope.addFinalizer(() =>
81
+ ref.semaphore.withPermits(1)(core.suspend(() => {
82
+ const close = ref.state._tag === "Acquired"
83
+ ? core.scopeClose(ref.state.scope, core.exitVoid)
84
+ : core.void
85
+ ref.state = stateClosed
86
+ return close
87
+ }))
88
+ ),
89
+ ref
90
+ )
91
+ })
92
+
93
+ /** @internal */
94
+ export const get = <A, E>(
95
+ self_: RcRef.RcRef<A, E>
96
+ ): Effect<A, E, Scope.Scope> => {
97
+ const self = self_ as RcRefImpl<A, E>
98
+ return core.uninterruptibleMask((restore) =>
99
+ core.suspend(() => {
100
+ switch (self.state._tag) {
101
+ case "Closed": {
102
+ return core.interrupt
103
+ }
104
+ case "Acquired": {
105
+ self.state.refCount++
106
+ return self.state.fiber
107
+ ? core.as(core.interruptFiber(self.state.fiber), self.state)
108
+ : core.succeed(self.state)
109
+ }
110
+ case "Empty": {
111
+ return fiberRuntime.scopeMake().pipe(
112
+ coreEffect.bindTo("scope"),
113
+ coreEffect.bind("value", ({ scope }) =>
114
+ restore(core.fiberRefLocally(
115
+ self.acquire as Effect<A, E>,
116
+ core.currentContext,
117
+ Context.add(self.context, fiberRuntime.scopeTag, scope)
118
+ ))),
119
+ core.map(({ scope, value }) => {
120
+ const state: State.Acquired<A> = {
121
+ _tag: "Acquired",
122
+ value,
123
+ scope,
124
+ fiber: undefined,
125
+ refCount: 1
126
+ }
127
+ self.state = state
128
+ return state
129
+ })
130
+ )
131
+ }
132
+ }
133
+ })
134
+ ).pipe(
135
+ self.semaphore.withPermits(1),
136
+ coreEffect.bindTo("state"),
137
+ coreEffect.bind("scope", () => fiberRuntime.scopeTag),
138
+ core.tap(({ scope, state }) =>
139
+ scope.addFinalizer(() =>
140
+ core.suspend(() => {
141
+ state.refCount--
142
+ if (state.refCount > 0) {
143
+ return core.void
144
+ }
145
+ if (self.idleTimeToLive === undefined) {
146
+ self.state = stateEmpty
147
+ return core.scopeClose(state.scope, core.exitVoid)
148
+ }
149
+ return coreEffect.sleep(self.idleTimeToLive).pipe(
150
+ core.interruptible,
151
+ core.zipRight(core.suspend(() => {
152
+ if (self.state._tag === "Acquired" && self.state.refCount === 0) {
153
+ self.state = stateEmpty
154
+ return core.scopeClose(state.scope, core.exitVoid)
155
+ }
156
+ return core.void
157
+ })),
158
+ fiberRuntime.ensuring(core.sync(() => {
159
+ state.fiber = undefined
160
+ })),
161
+ circular.forkIn(self.scope),
162
+ core.tap((fiber) => {
163
+ state.fiber = fiber
164
+ }),
165
+ self.semaphore.withPermits(1)
166
+ )
167
+ })
168
+ )
169
+ ),
170
+ core.map(({ state }) => state.value)
171
+ )
172
+ }