@fncts/io 0.0.30 → 0.0.32
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/Channel/api/runScoped.d.ts +1 -0
- package/Channel/api.d.ts +1 -0
- package/Channel/internal/ChannelExecutor.d.ts +2 -2
- package/Fiber/FiberMessage.d.ts +5 -5
- package/IO/api/blocking.d.ts +7 -0
- package/IO/api/provideSomeLayer.d.ts +1 -2
- package/IO/api/zipConcurrent.d.ts +2 -1
- package/IO/runtime.d.ts +4 -2
- package/IO.d.ts +1 -0
- package/Ref/Synchronized/definition.d.ts +3 -3
- package/Semaphore.d.ts +30 -0
- package/Stream/api.d.ts +24 -4
- package/SubscriptionRef.d.ts +3 -3
- package/_cjs/Channel/api/mapOutConcurrentIO.cjs +14 -16
- package/_cjs/Channel/api/mapOutConcurrentIO.cjs.map +1 -1
- package/_cjs/Channel/api/mergeAllWith.cjs +30 -32
- package/_cjs/Channel/api/mergeAllWith.cjs.map +1 -1
- package/_cjs/Channel/api/runScoped.cjs +19 -3
- package/_cjs/Channel/api/runScoped.cjs.map +1 -1
- package/_cjs/Channel/api/toPull.cjs +1 -1
- package/_cjs/Channel/api/toPull.cjs.map +1 -1
- package/_cjs/Channel/api.cjs +3 -2
- package/_cjs/Channel/api.cjs.map +1 -1
- package/_cjs/Channel/internal/ChannelExecutor.cjs +61 -52
- package/_cjs/Channel/internal/ChannelExecutor.cjs.map +1 -1
- package/_cjs/Fiber/FiberMessage.cjs +12 -11
- package/_cjs/Fiber/FiberMessage.cjs.map +1 -1
- package/_cjs/Fiber/FiberRuntime.cjs +28 -27
- package/_cjs/Fiber/FiberRuntime.cjs.map +1 -1
- package/_cjs/FiberScope/definition.cjs +2 -2
- package/_cjs/FiberScope/definition.cjs.map +1 -1
- package/_cjs/Hub/api.cjs.map +1 -1
- package/_cjs/{RuntimeConfig.cjs → IO/api/blocking.cjs} +13 -5
- package/_cjs/IO/api/blocking.cjs.map +1 -0
- package/_cjs/IO/api/provideSomeLayer.cjs.map +1 -1
- package/_cjs/IO/api/raceWith.cjs +9 -12
- package/_cjs/IO/api/raceWith.cjs.map +1 -1
- package/_cjs/IO/api/stateful.cjs +3 -3
- package/_cjs/IO/api/stateful.cjs.map +1 -1
- package/_cjs/IO/api/withChildren.cjs +5 -4
- package/_cjs/IO/api/withChildren.cjs.map +1 -1
- package/_cjs/IO/api/zipConcurrent.cjs +23 -23
- package/_cjs/IO/api/zipConcurrent.cjs.map +1 -1
- package/_cjs/IO/runtime.cjs +8 -8
- package/_cjs/IO/runtime.cjs.map +1 -1
- package/_cjs/IO.cjs +11 -0
- package/_cjs/IO.cjs.map +1 -1
- package/_cjs/Queue/api/filterInputIO.cjs.map +1 -1
- package/_cjs/Queue/api/filterOutputIO.cjs.map +1 -1
- package/_cjs/Ref/Synchronized/constructors.cjs +4 -5
- package/_cjs/Ref/Synchronized/constructors.cjs.map +1 -1
- package/_cjs/Ref/Synchronized/definition.cjs +1 -2
- package/_cjs/Ref/Synchronized/definition.cjs.map +1 -1
- package/_cjs/Semaphore.cjs +90 -0
- package/_cjs/Semaphore.cjs.map +1 -0
- package/_cjs/Stream/api.cjs +101 -61
- package/_cjs/Stream/api.cjs.map +1 -1
- package/_cjs/SubscriptionRef.cjs +2 -3
- package/_cjs/SubscriptionRef.cjs.map +1 -1
- package/_cjs/internal/BackgroundScheduler.cjs +199 -0
- package/_cjs/internal/BackgroundScheduler.cjs.map +1 -0
- package/_mjs/Cached/definition.mjs.map +1 -1
- package/_mjs/Channel/api/mapOutConcurrentIO.mjs +14 -16
- package/_mjs/Channel/api/mapOutConcurrentIO.mjs.map +1 -1
- package/_mjs/Channel/api/mergeAllWith.mjs +30 -32
- package/_mjs/Channel/api/mergeAllWith.mjs.map +1 -1
- package/_mjs/Channel/api/runScoped.mjs +19 -3
- package/_mjs/Channel/api/runScoped.mjs.map +1 -1
- package/_mjs/Channel/api/toPull.mjs +1 -1
- package/_mjs/Channel/api/toPull.mjs.map +1 -1
- package/_mjs/Channel/api.mjs +3 -2
- package/_mjs/Channel/api.mjs.map +1 -1
- package/_mjs/Channel/internal/ChannelExecutor.mjs +61 -52
- package/_mjs/Channel/internal/ChannelExecutor.mjs.map +1 -1
- package/_mjs/Fiber/FiberMessage.mjs +5 -5
- package/_mjs/Fiber/FiberMessage.mjs.map +1 -1
- package/_mjs/Fiber/FiberRuntime.mjs +28 -27
- package/_mjs/Fiber/FiberRuntime.mjs.map +1 -1
- package/_mjs/FiberScope/definition.mjs +2 -2
- package/_mjs/FiberScope/definition.mjs.map +1 -1
- package/_mjs/Hub/api.mjs.map +1 -1
- package/_mjs/IO/api/blocking.mjs +12 -0
- package/_mjs/IO/api/blocking.mjs.map +1 -0
- package/_mjs/IO/api/provideSomeLayer.mjs.map +1 -1
- package/_mjs/IO/api/raceWith.mjs +9 -12
- package/_mjs/IO/api/raceWith.mjs.map +1 -1
- package/_mjs/IO/api/stateful.mjs +3 -3
- package/_mjs/IO/api/stateful.mjs.map +1 -1
- package/_mjs/IO/api/withChildren.mjs +5 -4
- package/_mjs/IO/api/withChildren.mjs.map +1 -1
- package/_mjs/IO/api/zipConcurrent.mjs +23 -23
- package/_mjs/IO/api/zipConcurrent.mjs.map +1 -1
- package/_mjs/IO/runtime.mjs +6 -6
- package/_mjs/IO/runtime.mjs.map +1 -1
- package/_mjs/IO.mjs +1 -0
- package/_mjs/IO.mjs.map +1 -1
- package/_mjs/Queue/api/filterInputIO.mjs.map +1 -1
- package/_mjs/Queue/api/filterOutputIO.mjs.map +1 -1
- package/_mjs/Ref/Synchronized/constructors.mjs +4 -5
- package/_mjs/Ref/Synchronized/constructors.mjs.map +1 -1
- package/_mjs/Ref/Synchronized/definition.mjs +1 -2
- package/_mjs/Ref/Synchronized/definition.mjs.map +1 -1
- package/_mjs/Semaphore.mjs +78 -0
- package/_mjs/Semaphore.mjs.map +1 -0
- package/_mjs/Stream/api.mjs +93 -57
- package/_mjs/Stream/api.mjs.map +1 -1
- package/_mjs/SubscriptionRef.mjs +2 -3
- package/_mjs/SubscriptionRef.mjs.map +1 -1
- package/_mjs/internal/BackgroundScheduler.mjs +191 -0
- package/_mjs/internal/BackgroundScheduler.mjs.map +1 -0
- package/_src/Cached/definition.ts +1 -1
- package/_src/Channel/api/mapOutConcurrentIO.ts +1 -1
- package/_src/Channel/api/mergeAllWith.ts +1 -1
- package/_src/Channel/api/runScoped.ts +30 -5
- package/_src/Channel/api/toPull.ts +1 -1
- package/_src/Channel/api.ts +1 -0
- package/_src/Channel/internal/ChannelExecutor.ts +24 -20
- package/_src/Fiber/FiberMessage.ts +5 -5
- package/_src/Fiber/FiberRuntime.ts +1 -1
- package/_src/FiberRefs/api.ts +1 -1
- package/_src/Hub/api.ts +1 -1
- package/_src/IO/api/blocking.ts +9 -0
- package/_src/IO/api/provideSomeLayer.ts +1 -3
- package/_src/IO/api/raceWith.ts +1 -3
- package/_src/IO/api/stateful.ts +1 -1
- package/_src/IO/api/zipConcurrent.ts +26 -30
- package/_src/IO/runtime.ts +4 -4
- package/_src/IO.ts +1 -0
- package/_src/Queue/api/filterInputIO.ts +1 -1
- package/_src/Queue/api/filterOutputIO.ts +1 -1
- package/_src/Ref/Synchronized/constructors.ts +2 -2
- package/_src/Ref/Synchronized/definition.ts +1 -1
- package/_src/Semaphore.ts +81 -0
- package/_src/State/definition.ts +1 -1
- package/_src/Stream/api.ts +58 -7
- package/_src/Subject/Atomic.ts +1 -1
- package/_src/SubscriptionRef.ts +2 -2
- package/_src/global.ts +4 -4
- package/_src/index.ts +2 -2
- package/_src/internal/BackgroundScheduler.ts +276 -0
- package/global.d.ts +4 -4
- package/index.d.ts +2 -2
- package/internal/BackgroundScheduler.d.ts +47 -0
- package/package.json +3 -3
- package/RuntimeConfig.d.ts +0 -11
- package/_cjs/RuntimeConfig.cjs.map +0 -1
- package/_mjs/RuntimeConfig.mjs +0 -3
- package/_mjs/RuntimeConfig.mjs.map +0 -1
- package/_src/RuntimeConfig.ts +0 -6
|
@@ -19,7 +19,7 @@ export function mapOutConcurrentIO<OutElem, Env1, OutErr1, OutElem1>(
|
|
|
19
19
|
),
|
|
20
20
|
);
|
|
21
21
|
const errorSignal = Δ(Future.make<OutErr1, never>());
|
|
22
|
-
const permits = Δ(
|
|
22
|
+
const permits = Δ(Semaphore(n));
|
|
23
23
|
const pull = Δ(self.toPull);
|
|
24
24
|
Δ(
|
|
25
25
|
pull.matchCauseIO(
|
|
@@ -35,7 +35,7 @@ export function mergeAllWith<OutDone>(
|
|
|
35
35
|
const cancelers = Δ(IO.acquireRelease(Queue.makeUnbounded<Future<never, void>>(), (queue) => queue.shutdown));
|
|
36
36
|
const lastDone = Δ(Ref.make<Maybe<OutDone>>(Nothing()));
|
|
37
37
|
const errorSignal = Δ(Future.make<never, void>());
|
|
38
|
-
const permits = Δ(
|
|
38
|
+
const permits = Δ(Semaphore(n));
|
|
39
39
|
const pull = Δ(channels.toPull);
|
|
40
40
|
const evaluatePull = (pull: IO<Env | Env1, OutErr | OutErr1, Either<OutDone, OutElem>>) =>
|
|
41
41
|
pull
|
|
@@ -23,7 +23,11 @@ function runScopedInterpret<Env, InErr, InDone, OutErr, OutDone>(
|
|
|
23
23
|
return IO.fromExit(exec.getDone());
|
|
24
24
|
}
|
|
25
25
|
case ChannelStateTag.Read: {
|
|
26
|
-
return readUpstream(
|
|
26
|
+
return readUpstream(
|
|
27
|
+
channelState,
|
|
28
|
+
() => runScopedInterpret(exec.run(), exec),
|
|
29
|
+
(cause) => IO.refailCause(cause),
|
|
30
|
+
);
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
}
|
|
@@ -38,8 +42,29 @@ function runScopedInterpret<Env, InErr, InDone, OutErr, OutDone>(
|
|
|
38
42
|
export function runScoped<Env, InErr, InDone, OutErr, OutDone>(
|
|
39
43
|
self: Channel<Env, InErr, unknown, InDone, OutErr, never, OutDone>,
|
|
40
44
|
): IO<Env | Scope, OutErr, OutDone> {
|
|
41
|
-
|
|
42
|
-
IO.succeed(new ChannelExecutor(() => self, null, identity)),
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
const run = (channelFuture: Future<OutErr, OutDone>, scopeFuture: Future<never, void>, scope: Scope) =>
|
|
46
|
+
IO.acquireReleaseExit(IO.succeed(new ChannelExecutor(() => self, null, identity)), (exec, exit) => {
|
|
47
|
+
const finalize = exec.close(exit);
|
|
48
|
+
if (finalize !== null) {
|
|
49
|
+
return finalize.tapErrorCause((cause) => scope.addFinalizer(IO.refailCause(cause)));
|
|
50
|
+
} else {
|
|
51
|
+
return IO.unit;
|
|
52
|
+
}
|
|
53
|
+
}).flatMap((exec) =>
|
|
54
|
+
IO.defer(runScopedInterpret(exec.run(), exec).fulfill(channelFuture) > channelFuture.await < scopeFuture.await),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
return IO.uninterruptibleMask((restore) =>
|
|
58
|
+
Do((Δ) => {
|
|
59
|
+
const parent = Δ(IO.scope);
|
|
60
|
+
const child = Δ(parent.fork);
|
|
61
|
+
const channelFuture = Δ(Future.make<OutErr, OutDone>());
|
|
62
|
+
const scopeFuture = Δ(Future.make<never, void>());
|
|
63
|
+
const fiber = Δ(restore(run(channelFuture, scopeFuture, child)).forkScoped);
|
|
64
|
+
Δ(IO.addFinalizer(scopeFuture.succeed(undefined)));
|
|
65
|
+
const done = Δ(restore(channelFuture.await));
|
|
66
|
+
Δ(fiber.inheritAll);
|
|
67
|
+
return done;
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
45
70
|
}
|
|
@@ -32,7 +32,7 @@ function toPullInterpret<Env, InErr, InElem, InDone, OutErr, OutElem, OutDone>(
|
|
|
32
32
|
return done.match(IO.failCauseNow, (outDone) => IO.succeedNow(Either.left(outDone)));
|
|
33
33
|
}
|
|
34
34
|
case ChannelStateTag.Read: {
|
|
35
|
-
return readUpstream(channelState, () => toPullInterpret(exec.run(), exec));
|
|
35
|
+
return readUpstream(channelState, () => toPullInterpret(exec.run(), exec), IO.refailCause);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
package/_src/Channel/api.ts
CHANGED
|
@@ -1028,6 +1028,7 @@ function isChannelFailure<E>(u: unknown): u is ChannelFailure<E> {
|
|
|
1028
1028
|
|
|
1029
1029
|
/**
|
|
1030
1030
|
* @tsplus pipeable fncts.io.Channel pipeToOrFail
|
|
1031
|
+
* @tsplus pipeable-operator fncts.io.Channel >>>
|
|
1031
1032
|
*/
|
|
1032
1033
|
export function pipeToOrFail<OutElem, OutDone, Env1, OutErr1, OutElem1, OutDone1>(
|
|
1033
1034
|
right: Channel<Env1, never, OutElem, OutDone, OutErr1, OutElem1, OutDone1>,
|
|
@@ -184,9 +184,13 @@ class Emit<R> {
|
|
|
184
184
|
* ChannelExecutor
|
|
185
185
|
* -------------------------------------------------------------------------------------------------
|
|
186
186
|
*/
|
|
187
|
-
export function readUpstream<R, E, A
|
|
187
|
+
export function readUpstream<R, E, A, E1>(
|
|
188
|
+
r: State.Read<R, E>,
|
|
189
|
+
cont: () => IO<R, E1, A>,
|
|
190
|
+
onFailure: (cause: Cause<E>) => IO<R, E1, A>,
|
|
191
|
+
): IO<R, E1, A> {
|
|
188
192
|
const readStack: Stack<State.Read<any, any>> = Stack.single(r);
|
|
189
|
-
const read = (): IO<R,
|
|
193
|
+
const read = (): IO<R, E1, A> => {
|
|
190
194
|
const current = readStack.pop()!;
|
|
191
195
|
if (current.upstream === null) {
|
|
192
196
|
return IO.defer(cont);
|
|
@@ -199,13 +203,13 @@ export function readUpstream<R, E, A>(r: State.Read<R, E>, cont: () => IO<R, E,
|
|
|
199
203
|
if (emitEffect === null) {
|
|
200
204
|
return IO.defer(cont());
|
|
201
205
|
} else {
|
|
202
|
-
return emitEffect.
|
|
206
|
+
return emitEffect.matchCauseIO(onFailure, () => cont());
|
|
203
207
|
}
|
|
204
208
|
} else {
|
|
205
209
|
if (emitEffect === null) {
|
|
206
210
|
return IO.defer(read());
|
|
207
211
|
} else {
|
|
208
|
-
return emitEffect.
|
|
212
|
+
return emitEffect.matchCauseIO(onFailure, () => read());
|
|
209
213
|
}
|
|
210
214
|
}
|
|
211
215
|
}
|
|
@@ -215,13 +219,13 @@ export function readUpstream<R, E, A>(r: State.Read<R, E>, cont: () => IO<R, E,
|
|
|
215
219
|
if (doneEffect === null) {
|
|
216
220
|
return IO.defer(cont());
|
|
217
221
|
} else {
|
|
218
|
-
return doneEffect.
|
|
222
|
+
return doneEffect.matchCauseIO(onFailure, () => cont());
|
|
219
223
|
}
|
|
220
224
|
} else {
|
|
221
225
|
if (doneEffect === null) {
|
|
222
226
|
return IO.defer(read());
|
|
223
227
|
} else {
|
|
224
|
-
return doneEffect.
|
|
228
|
+
return doneEffect.matchCauseIO(onFailure, () => read());
|
|
225
229
|
}
|
|
226
230
|
}
|
|
227
231
|
}
|
|
@@ -321,8 +325,10 @@ export class ChannelExecutor<Env, InErr, InElem, InDone, OutErr, OutElem, OutDon
|
|
|
321
325
|
);
|
|
322
326
|
}
|
|
323
327
|
case State.ChannelStateTag.Read: {
|
|
324
|
-
return readUpstream(
|
|
325
|
-
|
|
328
|
+
return readUpstream(
|
|
329
|
+
state,
|
|
330
|
+
() => drainer,
|
|
331
|
+
(cause: Cause<any>) => currentChannel.input.error(cause),
|
|
326
332
|
);
|
|
327
333
|
}
|
|
328
334
|
}
|
|
@@ -492,26 +498,24 @@ export class ChannelExecutor<Env, InErr, InElem, InDone, OutErr, OutElem, OutDon
|
|
|
492
498
|
|
|
493
499
|
private popAllFinalizers(exit: Exit<unknown, unknown>): URIO<Env, any> {
|
|
494
500
|
/**
|
|
495
|
-
* @tsplus
|
|
501
|
+
* @tsplus tailRec
|
|
496
502
|
*/
|
|
497
|
-
const unwind = (
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
): IO<Env, never, Exit<never, unknown>> => {
|
|
501
|
-
if (conts.isEmpty()) {
|
|
502
|
-
return acc;
|
|
503
|
+
const unwind = (acc: List<Finalizer<Env>>): List<Finalizer<Env>> => {
|
|
504
|
+
if (this.doneStack.isEmpty()) {
|
|
505
|
+
return acc.reverse;
|
|
503
506
|
} else {
|
|
504
|
-
const head
|
|
507
|
+
const head = this.doneStack.unsafeHead;
|
|
508
|
+
this.doneStack = this.doneStack.unsafeTail;
|
|
505
509
|
concreteContinuation(head);
|
|
506
510
|
if (head._tag === ChannelTag.ContinuationK) {
|
|
507
|
-
return unwind(acc
|
|
511
|
+
return unwind(acc);
|
|
508
512
|
} else {
|
|
509
|
-
return unwind(acc.
|
|
513
|
+
return unwind(acc.prepend(head.finalizer));
|
|
510
514
|
}
|
|
511
515
|
}
|
|
512
516
|
};
|
|
513
|
-
const
|
|
514
|
-
|
|
517
|
+
const finalizers = unwind(List.empty());
|
|
518
|
+
const effect = finalizers.isEmpty() ? IO.unit : this.runFinalizers(finalizers, exit);
|
|
515
519
|
this.storeInProgressFinalizer(effect);
|
|
516
520
|
return effect;
|
|
517
521
|
}
|
|
@@ -26,7 +26,7 @@ export class InterruptSignal {
|
|
|
26
26
|
/**
|
|
27
27
|
* @tsplus static fncts.io.FiberMessageOps InterruptSignal
|
|
28
28
|
*/
|
|
29
|
-
export function
|
|
29
|
+
export function interruptSignal(cause: Cause<never>): FiberMessage {
|
|
30
30
|
return new InterruptSignal(cause);
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ export class GenStackTrace {
|
|
|
38
38
|
/**
|
|
39
39
|
* @tsplus static fncts.io.FiberMessageOps GenStackTrace
|
|
40
40
|
*/
|
|
41
|
-
export function
|
|
41
|
+
export function genStackTrace(onTrace: (trace: Trace) => void): FiberMessage {
|
|
42
42
|
return new GenStackTrace(onTrace);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -50,7 +50,7 @@ export class Stateful {
|
|
|
50
50
|
/**
|
|
51
51
|
* @tsplus static fncts.io.FiberMessageOps Stateful
|
|
52
52
|
*/
|
|
53
|
-
export function
|
|
53
|
+
export function stateful(onFiber: (fiber: FiberRuntime<any, any>, status: FiberStatus) => void): FiberMessage {
|
|
54
54
|
return new Stateful(onFiber);
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -62,7 +62,7 @@ export class Resume {
|
|
|
62
62
|
/**
|
|
63
63
|
* @tsplus static fncts.io.FiberMessageOps Resume
|
|
64
64
|
*/
|
|
65
|
-
export function
|
|
65
|
+
export function resume(cont: IO<any, any, any>): FiberMessage {
|
|
66
66
|
return new Resume(cont);
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -73,6 +73,6 @@ export interface YieldNow {
|
|
|
73
73
|
/**
|
|
74
74
|
* @tsplus static fncts.io.FiberMessageOps YieldNow
|
|
75
75
|
*/
|
|
76
|
-
export const
|
|
76
|
+
export const yieldNow: FiberMessage = {
|
|
77
77
|
_tag: FiberMessageTag.YieldNow,
|
|
78
78
|
};
|
|
@@ -506,7 +506,7 @@ export class FiberRuntime<E, A> implements Fiber.Runtime<E, A> {
|
|
|
506
506
|
} else if (isInterruptedException(e)) {
|
|
507
507
|
cur = IO.concrete(IO.failCauseNow(Cause.both(Cause.halt(e), Cause.interrupt(FiberId.none))));
|
|
508
508
|
} else {
|
|
509
|
-
cur = IO.concrete(IO.failCauseNow(Cause.halt(e)));
|
|
509
|
+
cur = IO.concrete(IO.failCauseNow(Cause.halt(e, Trace(this.fiberId, Conc(TraceElement.parse(lastTrace))))));
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
512
|
}
|
package/_src/FiberRefs/api.ts
CHANGED
package/_src/Hub/api.ts
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
unsafeMakeHub,
|
|
12
12
|
} from "@fncts/io/Hub/internal";
|
|
13
13
|
import { Hub as HubInternal } from "@fncts/io/internal/Hub";
|
|
14
|
-
import { EnqueueTypeId, QueueTypeId
|
|
14
|
+
import { EnqueueTypeId, QueueTypeId, QueueVariance } from "@fncts/io/Queue";
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Waits for the hub to be shut down.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { backgroundScheduler } from "@fncts/io/internal/BackgroundScheduler";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @tsplus static fncts.io.IOOps blocking
|
|
5
|
+
* @tsplus getter fncts.io.IO blocking
|
|
6
|
+
*/
|
|
7
|
+
export function blocking<R, E, A>(self: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
|
|
8
|
+
return FiberRef.currentScheduler.locally(backgroundScheduler)(IO.yieldNow) > self;
|
|
9
|
+
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
import type { Spreadable } from "@fncts/base/types";
|
|
2
|
-
import type { Erase } from "@fncts/typelevel/Intersection";
|
|
3
1
|
/**
|
|
4
2
|
* @tsplus static fncts.io.IOAspects provideSomeLayer
|
|
5
3
|
* @tsplus pipeable fncts.io.IO provideSomeLayer
|
|
6
4
|
*/
|
|
7
5
|
export function provideSomeLayer<RIn, E1, ROut>(layer: Layer<RIn, E1, ROut>, __tsplusTrace?: string) {
|
|
8
|
-
return <R, E, A>(self: IO<R, E, A>): IO<RIn
|
|
6
|
+
return <R, E, A>(self: IO<R, E, A>): IO<RIn | Exclude<R, ROut>, E | E1, A> => {
|
|
9
7
|
// @ts-expect-error
|
|
10
8
|
return self.provideLayer(Layer.environment<RIn>().and(layer));
|
|
11
9
|
};
|
package/_src/IO/api/raceWith.ts
CHANGED
|
@@ -31,15 +31,13 @@ export function raceFibersWith<R, E, A, R1, E1, B, R2, E2, C, R3, E3, D>(
|
|
|
31
31
|
const raceIndicator = new AtomicBoolean(true);
|
|
32
32
|
const leftFiber = IO.unsafeMakeChildFiber(left, parentState, parentRuntimeFlags, null, __tsplusTrace);
|
|
33
33
|
const rightFiber = IO.unsafeMakeChildFiber(right0, parentState, parentRuntimeFlags, null, __tsplusTrace);
|
|
34
|
-
leftFiber.setFiberRef(FiberRef.forkScopeOverride, Just(parentState.scope));
|
|
35
|
-
rightFiber.setFiberRef(FiberRef.forkScopeOverride, Just(parentState.scope));
|
|
36
34
|
|
|
37
35
|
return IO.async((cb) => {
|
|
38
36
|
leftFiber.addObserver(() => complete(leftFiber, rightFiber, leftWins, raceIndicator, cb));
|
|
39
37
|
rightFiber.addObserver(() => complete(rightFiber, leftFiber, rightWins, raceIndicator, cb));
|
|
40
38
|
leftFiber.startFork(left);
|
|
41
39
|
rightFiber.startFork(right0);
|
|
42
|
-
});
|
|
40
|
+
}, leftFiber.fiberId.combine(rightFiber.fiberId));
|
|
43
41
|
});
|
|
44
42
|
};
|
|
45
43
|
}
|
package/_src/IO/api/stateful.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import type { InterruptibilityRestorer } from "./interrupt.js";
|
|
2
2
|
import type { Grafter } from "./transplant.js";
|
|
3
3
|
|
|
4
|
-
import { tuple } from "@fncts/base/data/function";
|
|
5
4
|
import { AtomicBoolean } from "@fncts/base/internal/AtomicBoolean";
|
|
6
|
-
import { AtomicReference } from "@fncts/base/internal/AtomicReference";
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* @tsplus pipeable fncts.io.IO zipConcurrent
|
|
10
8
|
*/
|
|
11
9
|
export function zipConcurrent<R1, E1, B>(that: IO<R1, E1, B>, __tsplusTrace?: string) {
|
|
12
|
-
return <R, E, A>(self: IO<R, E, A>): IO<R | R1, E | E1,
|
|
13
|
-
return self.zipWithConcurrent(that,
|
|
10
|
+
return <R, E, A>(self: IO<R, E, A>): IO<R | R1, E | E1, Zipped.Make<A, B>> => {
|
|
11
|
+
return self.zipWithConcurrent(that, (a, b) => Zipped(a, b));
|
|
14
12
|
};
|
|
15
13
|
}
|
|
16
14
|
|
|
@@ -19,32 +17,30 @@ export function zipConcurrent<R1, E1, B>(that: IO<R1, E1, B>, __tsplusTrace?: st
|
|
|
19
17
|
*/
|
|
20
18
|
export function zipWithConcurrent<A, R1, E1, B, C>(that: IO<R1, E1, B>, f: (a: A, b: B) => C, __tsplusTrace?: string) {
|
|
21
19
|
return <R, E>(self: IO<R, E, A>): IO<R | R1, E | E1, C> => {
|
|
22
|
-
return IO.
|
|
23
|
-
IO.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
left
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
.
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}),
|
|
47
|
-
);
|
|
20
|
+
return IO.uninterruptibleMask((restore) => {
|
|
21
|
+
return IO.transplant((graft) => {
|
|
22
|
+
const future = Future.unsafeMake<void, void>(FiberId.none);
|
|
23
|
+
const ref = new AtomicBoolean(false);
|
|
24
|
+
return fork(self, restore, graft, future, ref)
|
|
25
|
+
.zip(fork(that, restore, graft, future, ref))
|
|
26
|
+
.flatMap(([left, right]) =>
|
|
27
|
+
restore(future.await).matchCauseIO(
|
|
28
|
+
(cause) =>
|
|
29
|
+
left.interruptFork >
|
|
30
|
+
right.interruptFork >
|
|
31
|
+
left.await.zip(right.await).flatMap(([left, right]) =>
|
|
32
|
+
left
|
|
33
|
+
.zipWithCause(right, f, (a, b) => Cause.both(a, b))
|
|
34
|
+
.match(
|
|
35
|
+
(causes) => IO.refailCause(Cause.both(cause.stripFailures, causes)),
|
|
36
|
+
() => IO.refailCause(cause.stripFailures),
|
|
37
|
+
),
|
|
38
|
+
),
|
|
39
|
+
() => left.join.zipWith(right.join, f),
|
|
40
|
+
),
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
48
44
|
};
|
|
49
45
|
}
|
|
50
46
|
|
package/_src/IO/runtime.ts
CHANGED
|
@@ -59,7 +59,7 @@ export class Runtime<R> {
|
|
|
59
59
|
this.unsafeRunAsyncWith(io, resolve);
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
unsafeRunOrFork = <E, A>(io: IO<R, E, A>, __tsplusTrace?: string): Either<Fiber.Runtime<E, A>, Exit<E, A>> => {
|
|
63
63
|
const fiberId = FiberId.unsafeMake(__tsplusTrace);
|
|
64
64
|
const scheduler = new StagedScheduler();
|
|
65
65
|
const fiberRefs = this.fiberRefs.updateAs(fiberId, FiberRef.currentEnvironment, this.environment);
|
|
@@ -83,10 +83,10 @@ export class Runtime<R> {
|
|
|
83
83
|
|
|
84
84
|
const result = fiber.exitValue();
|
|
85
85
|
if (result !== null) {
|
|
86
|
-
return result;
|
|
86
|
+
return Either.right(result);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
return
|
|
89
|
+
return Either.left(fiber);
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -135,4 +135,4 @@ export const unsafeRunWith = defaultRuntime.unsafeRunWith;
|
|
|
135
135
|
/**
|
|
136
136
|
* @tsplus getter fncts.io.IO unsafeRunSyncExit
|
|
137
137
|
*/
|
|
138
|
-
export const
|
|
138
|
+
export const unsafeRunOrFork = defaultRuntime.unsafeRunOrFork;
|
package/_src/IO.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./IO/api/addFinalizer.js";
|
|
|
13
13
|
export * from "./IO/api/addFinalizerExit.js";
|
|
14
14
|
export * from "./IO/api/asyncInterrupt.js";
|
|
15
15
|
export * from "./IO/api/asyncIO.js";
|
|
16
|
+
export * from "./IO/api/blocking.js";
|
|
16
17
|
export * from "./IO/api/bracket.js";
|
|
17
18
|
export * from "./IO/api/bracketExit.js";
|
|
18
19
|
export * from "./IO/api/clockWith.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PEnqueue, PEnqueueInternal } from "@fncts/io/Queue/definition";
|
|
2
2
|
|
|
3
|
-
import { concrete, EnqueueTypeId, QueueInternal, QueueTypeId
|
|
3
|
+
import { concrete, EnqueueTypeId, QueueInternal, QueueTypeId, QueueVariance } from "@fncts/io/Queue/definition";
|
|
4
4
|
|
|
5
5
|
class FilterInputIO<RA, RB, EA, EB, B, A, A1 extends A, R2, E2> extends QueueInternal<RA | R2, RB, EA | E2, EB, A1, B> {
|
|
6
6
|
constructor(readonly queue: QueueInternal<RA, RB, EA, EB, A, B>, readonly f: (_: A1) => IO<R2, E2, boolean>) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { PDequeue, PDequeueInternal } from "@fncts/io/Queue/definition";
|
|
2
2
|
|
|
3
|
-
import { concrete, DequeueTypeId, QueueInternal, QueueTypeId
|
|
3
|
+
import { concrete, DequeueTypeId, QueueInternal, QueueTypeId, QueueVariance } from "@fncts/io/Queue/definition";
|
|
4
4
|
|
|
5
5
|
class FilterOutputIO<RA, RB, EA, EB, A, B, RB1, EB1> extends QueueInternal<RA, RB | RB1, EA, EB | EB1, A, B> {
|
|
6
6
|
constructor(readonly queue: QueueInternal<RA, RB, EA, EB, A, B>, readonly f: (b: B) => IO<RB1, EB1, boolean>) {
|
|
@@ -5,7 +5,7 @@ import { PSynchronizedInternal } from "./definition.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export function unsafeMakeSynchronized<A>(a: A, __tsplusTrace?: string): Ref.Synchronized<A> {
|
|
7
7
|
const ref = Ref.unsafeMake(a);
|
|
8
|
-
const semaphore =
|
|
8
|
+
const semaphore = Semaphore.unsafeMake(1);
|
|
9
9
|
return new PSynchronizedInternal(semaphore, ref.get, (a: A) => ref.set(a));
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ export function unsafeMakeSynchronized<A>(a: A, __tsplusTrace?: string): Ref.Syn
|
|
|
15
15
|
export function makeSynchronized<A>(a: Lazy<A>, __tsplusTrace?: string): UIO<Ref.Synchronized<A>> {
|
|
16
16
|
return Do((_) => {
|
|
17
17
|
const ref = _(Ref.make(a));
|
|
18
|
-
const semaphore = _(
|
|
18
|
+
const semaphore = _(Semaphore(1));
|
|
19
19
|
return new PSynchronizedInternal(semaphore, ref.get, (a: A) => ref.set(a));
|
|
20
20
|
});
|
|
21
21
|
}
|
|
@@ -30,7 +30,7 @@ export const Synchronized: PSynchronizedOps = {};
|
|
|
30
30
|
export class PSynchronizedInternal<RA, RB, EA, EB, A, B> extends RefInternal<RA, RB, EA, EB, A, B> {
|
|
31
31
|
readonly [SynchronizedTypeId]: SynchronizedTypeId = SynchronizedTypeId;
|
|
32
32
|
constructor(
|
|
33
|
-
readonly semaphore:
|
|
33
|
+
readonly semaphore: Semaphore,
|
|
34
34
|
readonly unsafeGet: IO<RB, EB, B>,
|
|
35
35
|
readonly unsafeSet: (a: A) => IO<RA, EA, void>,
|
|
36
36
|
) {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tsplus type fncts.io.Semaphore
|
|
3
|
+
* @tsplus companion fncts.io.SemaphoreOps
|
|
4
|
+
*/
|
|
5
|
+
export class Semaphore {
|
|
6
|
+
constructor(readonly permits: number) {}
|
|
7
|
+
|
|
8
|
+
taken = 0;
|
|
9
|
+
waiters = new Set<() => void>();
|
|
10
|
+
|
|
11
|
+
get free(): number {
|
|
12
|
+
return this.permits - this.taken;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
runNext() {
|
|
16
|
+
const next = this.waiters.values().next();
|
|
17
|
+
if (!next.done) {
|
|
18
|
+
this.waiters.delete(next.value);
|
|
19
|
+
next.value();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
take(n: number) {
|
|
24
|
+
return IO.asyncInterrupt<never, never, number>((cb) => {
|
|
25
|
+
if (this.free < n) {
|
|
26
|
+
const observer = () => {
|
|
27
|
+
if (this.free >= n) {
|
|
28
|
+
this.waiters.delete(observer);
|
|
29
|
+
this.taken += n;
|
|
30
|
+
cb(IO.succeedNow(n));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
this.waiters.add(observer);
|
|
34
|
+
return Either.left(
|
|
35
|
+
IO(() => {
|
|
36
|
+
this.waiters.delete(observer);
|
|
37
|
+
}),
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
this.taken += n;
|
|
41
|
+
return Either.right(IO.succeedNow(n));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
release(n: number) {
|
|
46
|
+
return IO.withFiberRuntime<never, never, void>((fiber) => {
|
|
47
|
+
this.taken -= n;
|
|
48
|
+
fiber.getFiberRef(FiberRef.currentScheduler).scheduleTask(() => {
|
|
49
|
+
this.waiters.forEach((wake) => wake());
|
|
50
|
+
});
|
|
51
|
+
return IO.unit;
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
withPermits(permits: number) {
|
|
56
|
+
return <R, E, A>(io: IO<R, E, A>): IO<R, E, A> => {
|
|
57
|
+
return IO.uninterruptibleMask((restore) =>
|
|
58
|
+
restore(this.take(permits)).flatMap((permits) => restore(io).ensuring(this.release(permits))),
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
withPermit<R, E, A>(io: IO<R, E, A>): IO<R, E, A> {
|
|
64
|
+
return this.withPermits(1)(io);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @tsplus static fncts.io.SemaphoreOps unsafeMake
|
|
70
|
+
*/
|
|
71
|
+
export function unsafeMakeSemaphore(permits: number): Semaphore {
|
|
72
|
+
return new Semaphore(permits);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @tsplus static fncts.io.SemaphoreOps make
|
|
77
|
+
* @tsplus static fncts.io.SemaphoreOps __call
|
|
78
|
+
*/
|
|
79
|
+
export function makeSemaphore(permits: number, __tsplusTrace?: string): UIO<Semaphore> {
|
|
80
|
+
return IO(Semaphore.unsafeMake(permits));
|
|
81
|
+
}
|
package/_src/State/definition.ts
CHANGED