@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.
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";