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.
- package/RcMap/package.json +6 -0
- package/RcRef/package.json +6 -0
- package/dist/cjs/Cause.js +22 -1
- package/dist/cjs/Cause.js.map +1 -1
- package/dist/cjs/Channel.js.map +1 -1
- package/dist/cjs/Config.js.map +1 -1
- package/dist/cjs/Console.js.map +1 -1
- package/dist/cjs/Data.js +3 -1
- package/dist/cjs/Data.js.map +1 -1
- package/dist/cjs/Duration.js +23 -2
- package/dist/cjs/Duration.js.map +1 -1
- package/dist/cjs/Logger.js +11 -1
- package/dist/cjs/Logger.js.map +1 -1
- package/dist/cjs/PubSub.js.map +1 -1
- package/dist/cjs/Random.js +9 -1
- package/dist/cjs/Random.js.map +1 -1
- package/dist/cjs/RcMap.js +52 -0
- package/dist/cjs/RcMap.js.map +1 -0
- package/dist/cjs/RcRef.js +51 -0
- package/dist/cjs/RcRef.js.map +1 -0
- package/dist/cjs/Stream.js +29 -2
- package/dist/cjs/Stream.js.map +1 -1
- package/dist/cjs/index.js +6 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/cause.js +21 -5
- package/dist/cjs/internal/cause.js.map +1 -1
- package/dist/cjs/internal/channel/channelExecutor.js.map +1 -1
- package/dist/cjs/internal/channel.js.map +1 -1
- package/dist/cjs/internal/core-effect.js +0 -5
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/core.js +15 -10
- package/dist/cjs/internal/core.js.map +1 -1
- package/dist/cjs/internal/defaultServices.js +1 -1
- package/dist/cjs/internal/defaultServices.js.map +1 -1
- package/dist/cjs/internal/fiberRuntime.js +3 -1
- package/dist/cjs/internal/fiberRuntime.js.map +1 -1
- package/dist/cjs/internal/logger.js +128 -27
- package/dist/cjs/internal/logger.js.map +1 -1
- package/dist/cjs/internal/pubsub.js +216 -36
- package/dist/cjs/internal/pubsub.js.map +1 -1
- package/dist/cjs/internal/random.js +2 -1
- package/dist/cjs/internal/random.js.map +1 -1
- package/dist/cjs/internal/rcMap.js +129 -0
- package/dist/cjs/internal/rcMap.js.map +1 -0
- package/dist/cjs/internal/rcRef.js +122 -0
- package/dist/cjs/internal/rcRef.js.map +1 -0
- package/dist/cjs/internal/stream.js +57 -11
- package/dist/cjs/internal/stream.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/dts/Cause.d.ts +40 -1
- package/dist/dts/Cause.d.ts.map +1 -1
- package/dist/dts/Channel.d.ts +3 -3
- package/dist/dts/Channel.d.ts.map +1 -1
- package/dist/dts/Config.d.ts +5 -0
- package/dist/dts/Config.d.ts.map +1 -1
- package/dist/dts/Console.d.ts +2 -4
- package/dist/dts/Console.d.ts.map +1 -1
- package/dist/dts/Duration.d.ts +5 -0
- package/dist/dts/Duration.d.ts.map +1 -1
- package/dist/dts/Logger.d.ts +15 -0
- package/dist/dts/Logger.d.ts.map +1 -1
- package/dist/dts/PubSub.d.ts +15 -4
- package/dist/dts/PubSub.d.ts.map +1 -1
- package/dist/dts/Random.d.ts +8 -0
- package/dist/dts/Random.d.ts.map +1 -1
- package/dist/dts/RcMap.d.ts +93 -0
- package/dist/dts/RcMap.d.ts.map +1 -0
- package/dist/dts/RcRef.d.ts +83 -0
- package/dist/dts/RcRef.d.ts.map +1 -0
- package/dist/dts/Stream.d.ts +64 -26
- package/dist/dts/Stream.d.ts.map +1 -1
- package/dist/dts/index.d.ts +8 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core-effect.d.ts.map +1 -1
- package/dist/dts/internal/fiberRuntime.d.ts.map +1 -1
- package/dist/dts/internal/logger.d.ts.map +1 -1
- package/dist/dts/internal/random.d.ts +1 -1
- package/dist/dts/internal/random.d.ts.map +1 -1
- package/dist/dts/internal/rcMap.d.ts +2 -0
- package/dist/dts/internal/rcMap.d.ts.map +1 -0
- package/dist/dts/internal/rcRef.d.ts +2 -0
- package/dist/dts/internal/rcRef.d.ts.map +1 -0
- package/dist/dts/internal/stream.d.ts +1 -0
- package/dist/dts/internal/stream.d.ts.map +1 -1
- package/dist/esm/Cause.js +21 -0
- package/dist/esm/Cause.js.map +1 -1
- package/dist/esm/Channel.js.map +1 -1
- package/dist/esm/Config.js.map +1 -1
- package/dist/esm/Console.js.map +1 -1
- package/dist/esm/Data.js +3 -1
- package/dist/esm/Data.js.map +1 -1
- package/dist/esm/Duration.js +20 -0
- package/dist/esm/Duration.js.map +1 -1
- package/dist/esm/Logger.js +10 -0
- package/dist/esm/Logger.js.map +1 -1
- package/dist/esm/PubSub.js.map +1 -1
- package/dist/esm/Random.js +8 -0
- package/dist/esm/Random.js.map +1 -1
- package/dist/esm/RcMap.js +44 -0
- package/dist/esm/RcMap.js.map +1 -0
- package/dist/esm/RcRef.js +43 -0
- package/dist/esm/RcRef.js.map +1 -0
- package/dist/esm/Stream.js +27 -0
- package/dist/esm/Stream.js.map +1 -1
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/cause.js +21 -5
- package/dist/esm/internal/cause.js.map +1 -1
- package/dist/esm/internal/channel/channelExecutor.js.map +1 -1
- package/dist/esm/internal/channel.js.map +1 -1
- package/dist/esm/internal/core-effect.js +0 -5
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/core.js +11 -7
- package/dist/esm/internal/core.js.map +1 -1
- package/dist/esm/internal/defaultServices.js +1 -1
- package/dist/esm/internal/defaultServices.js.map +1 -1
- package/dist/esm/internal/fiberRuntime.js +2 -0
- package/dist/esm/internal/fiberRuntime.js.map +1 -1
- package/dist/esm/internal/logger.js +126 -26
- package/dist/esm/internal/logger.js.map +1 -1
- package/dist/esm/internal/pubsub.js +216 -36
- package/dist/esm/internal/pubsub.js.map +1 -1
- package/dist/esm/internal/random.js +2 -1
- package/dist/esm/internal/random.js.map +1 -1
- package/dist/esm/internal/rcMap.js +120 -0
- package/dist/esm/internal/rcMap.js.map +1 -0
- package/dist/esm/internal/rcRef.js +112 -0
- package/dist/esm/internal/rcRef.js.map +1 -0
- package/dist/esm/internal/stream.js +53 -8
- package/dist/esm/internal/stream.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/package.json +17 -1
- package/src/Cause.ts +47 -1
- package/src/Channel.ts +3 -3
- package/src/Config.ts +6 -0
- package/src/Console.ts +2 -4
- package/src/Data.ts +1 -1
- package/src/Duration.ts +18 -0
- package/src/Logger.ts +19 -0
- package/src/PubSub.ts +11 -4
- package/src/Random.ts +9 -0
- package/src/RcMap.ts +103 -0
- package/src/RcRef.ts +91 -0
- package/src/Stream.ts +83 -26
- package/src/index.ts +10 -0
- package/src/internal/cause.ts +26 -5
- package/src/internal/channel/channelExecutor.ts +1 -1
- package/src/internal/channel.ts +4 -3
- package/src/internal/core-effect.ts +0 -5
- package/src/internal/core.ts +19 -9
- package/src/internal/defaultServices.ts +1 -1
- package/src/internal/fiberRuntime.ts +6 -0
- package/src/internal/logger.ts +133 -27
- package/src/internal/pubsub.ts +249 -58
- package/src/internal/random.ts +2 -1
- package/src/internal/rcMap.ts +213 -0
- package/src/internal/rcRef.ts +172 -0
- package/src/internal/stream.ts +325 -111
- 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
|
+
}
|