@fncts/io 0.0.30 → 0.0.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. package/Channel/api/runScoped.d.ts +1 -0
  2. package/Channel/api.d.ts +1 -0
  3. package/Channel/internal/ChannelExecutor.d.ts +2 -2
  4. package/Fiber/FiberMessage.d.ts +5 -5
  5. package/IO/api/blocking.d.ts +7 -0
  6. package/IO/api/provideSomeLayer.d.ts +1 -2
  7. package/IO/api/zipConcurrent.d.ts +2 -1
  8. package/IO/runtime.d.ts +4 -2
  9. package/IO.d.ts +1 -0
  10. package/Ref/Synchronized/definition.d.ts +3 -3
  11. package/Semaphore.d.ts +30 -0
  12. package/Stream/api.d.ts +24 -4
  13. package/SubscriptionRef.d.ts +3 -3
  14. package/_cjs/Channel/api/mapOutConcurrentIO.cjs +14 -16
  15. package/_cjs/Channel/api/mapOutConcurrentIO.cjs.map +1 -1
  16. package/_cjs/Channel/api/mergeAllWith.cjs +30 -32
  17. package/_cjs/Channel/api/mergeAllWith.cjs.map +1 -1
  18. package/_cjs/Channel/api/runScoped.cjs +19 -3
  19. package/_cjs/Channel/api/runScoped.cjs.map +1 -1
  20. package/_cjs/Channel/api/toPull.cjs +1 -1
  21. package/_cjs/Channel/api/toPull.cjs.map +1 -1
  22. package/_cjs/Channel/api.cjs +3 -2
  23. package/_cjs/Channel/api.cjs.map +1 -1
  24. package/_cjs/Channel/internal/ChannelExecutor.cjs +61 -52
  25. package/_cjs/Channel/internal/ChannelExecutor.cjs.map +1 -1
  26. package/_cjs/Fiber/FiberMessage.cjs +12 -11
  27. package/_cjs/Fiber/FiberMessage.cjs.map +1 -1
  28. package/_cjs/Fiber/FiberRuntime.cjs +28 -27
  29. package/_cjs/Fiber/FiberRuntime.cjs.map +1 -1
  30. package/_cjs/FiberScope/definition.cjs +2 -2
  31. package/_cjs/FiberScope/definition.cjs.map +1 -1
  32. package/_cjs/Hub/api.cjs.map +1 -1
  33. package/_cjs/{RuntimeConfig.cjs → IO/api/blocking.cjs} +13 -5
  34. package/_cjs/IO/api/blocking.cjs.map +1 -0
  35. package/_cjs/IO/api/provideSomeLayer.cjs.map +1 -1
  36. package/_cjs/IO/api/raceWith.cjs +9 -12
  37. package/_cjs/IO/api/raceWith.cjs.map +1 -1
  38. package/_cjs/IO/api/stateful.cjs +3 -3
  39. package/_cjs/IO/api/stateful.cjs.map +1 -1
  40. package/_cjs/IO/api/withChildren.cjs +5 -4
  41. package/_cjs/IO/api/withChildren.cjs.map +1 -1
  42. package/_cjs/IO/api/zipConcurrent.cjs +23 -23
  43. package/_cjs/IO/api/zipConcurrent.cjs.map +1 -1
  44. package/_cjs/IO/runtime.cjs +8 -8
  45. package/_cjs/IO/runtime.cjs.map +1 -1
  46. package/_cjs/IO.cjs +11 -0
  47. package/_cjs/IO.cjs.map +1 -1
  48. package/_cjs/Queue/api/filterInputIO.cjs.map +1 -1
  49. package/_cjs/Queue/api/filterOutputIO.cjs.map +1 -1
  50. package/_cjs/Ref/Synchronized/constructors.cjs +4 -5
  51. package/_cjs/Ref/Synchronized/constructors.cjs.map +1 -1
  52. package/_cjs/Ref/Synchronized/definition.cjs +1 -2
  53. package/_cjs/Ref/Synchronized/definition.cjs.map +1 -1
  54. package/_cjs/Semaphore.cjs +90 -0
  55. package/_cjs/Semaphore.cjs.map +1 -0
  56. package/_cjs/Stream/api.cjs +101 -61
  57. package/_cjs/Stream/api.cjs.map +1 -1
  58. package/_cjs/SubscriptionRef.cjs +2 -3
  59. package/_cjs/SubscriptionRef.cjs.map +1 -1
  60. package/_cjs/internal/BackgroundScheduler.cjs +199 -0
  61. package/_cjs/internal/BackgroundScheduler.cjs.map +1 -0
  62. package/_mjs/Cached/definition.mjs.map +1 -1
  63. package/_mjs/Channel/api/mapOutConcurrentIO.mjs +14 -16
  64. package/_mjs/Channel/api/mapOutConcurrentIO.mjs.map +1 -1
  65. package/_mjs/Channel/api/mergeAllWith.mjs +30 -32
  66. package/_mjs/Channel/api/mergeAllWith.mjs.map +1 -1
  67. package/_mjs/Channel/api/runScoped.mjs +19 -3
  68. package/_mjs/Channel/api/runScoped.mjs.map +1 -1
  69. package/_mjs/Channel/api/toPull.mjs +1 -1
  70. package/_mjs/Channel/api/toPull.mjs.map +1 -1
  71. package/_mjs/Channel/api.mjs +3 -2
  72. package/_mjs/Channel/api.mjs.map +1 -1
  73. package/_mjs/Channel/internal/ChannelExecutor.mjs +61 -52
  74. package/_mjs/Channel/internal/ChannelExecutor.mjs.map +1 -1
  75. package/_mjs/Fiber/FiberMessage.mjs +5 -5
  76. package/_mjs/Fiber/FiberMessage.mjs.map +1 -1
  77. package/_mjs/Fiber/FiberRuntime.mjs +28 -27
  78. package/_mjs/Fiber/FiberRuntime.mjs.map +1 -1
  79. package/_mjs/FiberScope/definition.mjs +2 -2
  80. package/_mjs/FiberScope/definition.mjs.map +1 -1
  81. package/_mjs/Hub/api.mjs.map +1 -1
  82. package/_mjs/IO/api/blocking.mjs +12 -0
  83. package/_mjs/IO/api/blocking.mjs.map +1 -0
  84. package/_mjs/IO/api/provideSomeLayer.mjs.map +1 -1
  85. package/_mjs/IO/api/raceWith.mjs +9 -12
  86. package/_mjs/IO/api/raceWith.mjs.map +1 -1
  87. package/_mjs/IO/api/stateful.mjs +3 -3
  88. package/_mjs/IO/api/stateful.mjs.map +1 -1
  89. package/_mjs/IO/api/withChildren.mjs +5 -4
  90. package/_mjs/IO/api/withChildren.mjs.map +1 -1
  91. package/_mjs/IO/api/zipConcurrent.mjs +23 -23
  92. package/_mjs/IO/api/zipConcurrent.mjs.map +1 -1
  93. package/_mjs/IO/runtime.mjs +6 -6
  94. package/_mjs/IO/runtime.mjs.map +1 -1
  95. package/_mjs/IO.mjs +1 -0
  96. package/_mjs/IO.mjs.map +1 -1
  97. package/_mjs/Queue/api/filterInputIO.mjs.map +1 -1
  98. package/_mjs/Queue/api/filterOutputIO.mjs.map +1 -1
  99. package/_mjs/Ref/Synchronized/constructors.mjs +4 -5
  100. package/_mjs/Ref/Synchronized/constructors.mjs.map +1 -1
  101. package/_mjs/Ref/Synchronized/definition.mjs +1 -2
  102. package/_mjs/Ref/Synchronized/definition.mjs.map +1 -1
  103. package/_mjs/Semaphore.mjs +78 -0
  104. package/_mjs/Semaphore.mjs.map +1 -0
  105. package/_mjs/Stream/api.mjs +93 -57
  106. package/_mjs/Stream/api.mjs.map +1 -1
  107. package/_mjs/SubscriptionRef.mjs +2 -3
  108. package/_mjs/SubscriptionRef.mjs.map +1 -1
  109. package/_mjs/internal/BackgroundScheduler.mjs +191 -0
  110. package/_mjs/internal/BackgroundScheduler.mjs.map +1 -0
  111. package/_src/Cached/definition.ts +1 -1
  112. package/_src/Channel/api/mapOutConcurrentIO.ts +1 -1
  113. package/_src/Channel/api/mergeAllWith.ts +1 -1
  114. package/_src/Channel/api/runScoped.ts +30 -5
  115. package/_src/Channel/api/toPull.ts +1 -1
  116. package/_src/Channel/api.ts +1 -0
  117. package/_src/Channel/internal/ChannelExecutor.ts +24 -20
  118. package/_src/Fiber/FiberMessage.ts +5 -5
  119. package/_src/Fiber/FiberRuntime.ts +1 -1
  120. package/_src/FiberRefs/api.ts +1 -1
  121. package/_src/Hub/api.ts +1 -1
  122. package/_src/IO/api/blocking.ts +9 -0
  123. package/_src/IO/api/provideSomeLayer.ts +1 -3
  124. package/_src/IO/api/raceWith.ts +1 -3
  125. package/_src/IO/api/stateful.ts +1 -1
  126. package/_src/IO/api/zipConcurrent.ts +26 -30
  127. package/_src/IO/runtime.ts +4 -4
  128. package/_src/IO.ts +1 -0
  129. package/_src/Queue/api/filterInputIO.ts +1 -1
  130. package/_src/Queue/api/filterOutputIO.ts +1 -1
  131. package/_src/Ref/Synchronized/constructors.ts +2 -2
  132. package/_src/Ref/Synchronized/definition.ts +1 -1
  133. package/_src/Semaphore.ts +81 -0
  134. package/_src/State/definition.ts +1 -1
  135. package/_src/Stream/api.ts +58 -7
  136. package/_src/Subject/Atomic.ts +1 -1
  137. package/_src/SubscriptionRef.ts +2 -2
  138. package/_src/global.ts +4 -4
  139. package/_src/index.ts +2 -2
  140. package/_src/internal/BackgroundScheduler.ts +276 -0
  141. package/global.d.ts +4 -4
  142. package/index.d.ts +2 -2
  143. package/internal/BackgroundScheduler.d.ts +47 -0
  144. package/package.json +3 -3
  145. package/RuntimeConfig.d.ts +0 -11
  146. package/_cjs/RuntimeConfig.cjs.map +0 -1
  147. package/_mjs/RuntimeConfig.mjs +0 -3
  148. package/_mjs/RuntimeConfig.mjs.map +0 -1
  149. 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 = Δ(TSemaphore.make(n).commit);
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 = Δ(TSemaphore.make(n).commit);
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(channelState, () => runScopedInterpret(exec.run(), exec));
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
- return IO.acquireReleaseExit(
42
- IO.succeed(new ChannelExecutor(() => self, null, identity)),
43
- (exec, exit) => exec.close(exit) ?? IO.unit,
44
- ).flatMap((exec) => IO.defer(runScopedInterpret(exec.run(), exec)));
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
  }
@@ -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>(r: State.Read<R, E>, cont: () => IO<R, E, A>): IO<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, E, A> => {
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.flatMap(() => cont());
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.flatMap(() => read());
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.flatMap(() => cont());
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.flatMap(() => read());
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(state, () => drainer).catchAllCause((cause) =>
325
- currentChannel.input.error(cause),
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 tailrec
501
+ * @tsplus tailRec
496
502
  */
497
- const unwind = (
498
- acc: IO<Env, never, Exit<never, any>>,
499
- conts: List<ErasedContinuation<Env>>,
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 = conts.unsafeHead!;
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, conts.unsafeTail);
511
+ return unwind(acc);
508
512
  } else {
509
- return unwind(acc.zipRight(head.finalizer(exit).result), conts.unsafeTail);
513
+ return unwind(acc.prepend(head.finalizer));
510
514
  }
511
515
  }
512
516
  };
513
- const effect = unwind(IO.succeedNow(Exit.succeed(undefined)), this.doneStack).flatMap(IO.fromExitNow);
514
- this.doneStack = Nil();
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 mkInterruptSignal(cause: Cause<never>): FiberMessage {
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 mkGenStackTrace(onTrace: (trace: Trace) => void): FiberMessage {
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 mkStateful(onFiber: (fiber: FiberRuntime<any, any>, status: FiberStatus) => void): FiberMessage {
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 mkResume(cont: IO<any, any, any>): FiberMessage {
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 YieldNow: FiberMessage = {
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
  }
@@ -155,4 +155,4 @@ function findAncestor(
155
155
  }
156
156
  }
157
157
  return [ref.initial, true];
158
- }
158
+ }
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 , QueueVariance } from "@fncts/io/Queue";
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 & Erase<R, ROut>, E | E1, A> => {
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
  };
@@ -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
  }
@@ -9,5 +9,5 @@ export function stateful<S, R, E, A>(
9
9
  tag: Tag<State<S>>,
10
10
  __tsplusTrace?: string,
11
11
  ): IO<R, E, A> {
12
- return IO.defer(io)(IO.$.provideSomeLayer(State.initial(s, tag)));
12
+ return IO.defer(io).provideSomeLayer(State.initial(s, tag));
13
13
  }
@@ -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, readonly [A, B]> => {
13
- return self.zipWithConcurrent(that, tuple);
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.fiberId.flatMap((fiberId) =>
23
- IO.uninterruptibleMask((restore) => {
24
- return IO.transplant((graft) => {
25
- const future = Future.unsafeMake<void, void>(FiberId.none);
26
- const ref = new AtomicBoolean(false);
27
- return fork(self, restore, graft, future, ref)
28
- .zip(fork(that, restore, graft, future, ref))
29
- .flatMap(([left, right]) =>
30
- restore(future.await).matchCauseIO(
31
- (cause) =>
32
- left.interruptFork >
33
- right.interruptFork >
34
- left.await.zip(right.await).flatMap(([left, right]) =>
35
- left
36
- .zipWithCause(right, f, (a, b) => Cause.both(a, b))
37
- .match(
38
- (causes) => IO.refailCause(Cause.both(cause.stripFailures, causes)),
39
- () => IO.refailCause(cause.stripFailures),
40
- ),
41
- ),
42
- () => left.join.zipWith(right.join, f),
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
 
@@ -59,7 +59,7 @@ export class Runtime<R> {
59
59
  this.unsafeRunAsyncWith(io, resolve);
60
60
  });
61
61
 
62
- unsafeRunSyncExit = <E, A>(io: IO<R, E, A>, __tsplusTrace?: string): Exit<E, A> => {
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 Exit.halt(fiber);
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 unsafeRunSyncExit = defaultRuntime.unsafeRunSyncExit;
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 , QueueVariance } from "@fncts/io/Queue/definition";
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 , QueueVariance } from "@fncts/io/Queue/definition";
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 = TSemaphore.unsafeMake(1);
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 = _(TSemaphore.make(1).commit);
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: TSemaphore,
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
+ }
@@ -1,4 +1,4 @@
1
- import type { StateInternal} from "./internal.js";
1
+ import type { StateInternal } from "./internal.js";
2
2
 
3
3
  import { StateVariance } from "./internal.js";
4
4
  import { StateTypeId } from "./internal.js";