@fncts/io 0.0.24 → 0.0.26

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 (230) hide show
  1. package/FiberRef/api.d.ts +0 -63
  2. package/FiberRef/operations.d.ts +64 -0
  3. package/FiberRef.d.ts +1 -0
  4. package/FiberRefs/api.d.ts +6 -1
  5. package/FiberRefs.d.ts +0 -1
  6. package/IO/api/daemonChildren.d.ts +6 -0
  7. package/IO/api/disconnect.d.ts +17 -0
  8. package/IO/api/fork.d.ts +4 -0
  9. package/IO/api/forkDaemon.d.ts +10 -0
  10. package/IO/api/interrupt.d.ts +1 -20
  11. package/IO/api/race.d.ts +7 -1
  12. package/IO/api/raceWith.d.ts +17 -0
  13. package/IO/api/transplant.d.ts +13 -0
  14. package/IO/api/whenFiberRef.d.ts +10 -0
  15. package/IO/api/whenRef.d.ts +10 -0
  16. package/IO/api/zipConcurrent.d.ts +5 -4
  17. package/IO/api.d.ts +12 -1
  18. package/IO.d.ts +7 -1
  19. package/RefSubject/Atomic.d.ts +1 -1
  20. package/_cjs/Cached/api.cjs +1 -1
  21. package/_cjs/Channel/api/mergeAllWith.cjs +1 -1
  22. package/_cjs/Channel/api/mergeWith.cjs +17 -16
  23. package/_cjs/Channel/api/mergeWith.cjs.map +1 -1
  24. package/_cjs/Channel/api.cjs +1 -3
  25. package/_cjs/Channel/api.cjs.map +1 -1
  26. package/_cjs/Fiber/FiberRuntime.cjs +16 -17
  27. package/_cjs/Fiber/FiberRuntime.cjs.map +1 -1
  28. package/_cjs/FiberRef/api/locallyScoped.cjs +1 -1
  29. package/_cjs/FiberRef/api/locallyScopedWith.cjs +1 -1
  30. package/_cjs/FiberRef/api.cjs +0 -124
  31. package/_cjs/FiberRef/api.cjs.map +1 -1
  32. package/_cjs/FiberRef/constructors.cjs +1 -1
  33. package/_cjs/FiberRef/operations.cjs +130 -0
  34. package/_cjs/FiberRef/operations.cjs.map +1 -0
  35. package/_cjs/FiberRef.cjs +11 -0
  36. package/_cjs/FiberRef.cjs.map +1 -1
  37. package/_cjs/FiberRefs/api.cjs +90 -0
  38. package/_cjs/FiberRefs/api.cjs.map +1 -1
  39. package/_cjs/FiberRefs.cjs +0 -11
  40. package/_cjs/FiberRefs.cjs.map +1 -1
  41. package/_cjs/Future/api.cjs +1 -3
  42. package/_cjs/Future/api.cjs.map +1 -1
  43. package/_cjs/IO/api/asyncIO.cjs +1 -3
  44. package/_cjs/IO/api/asyncIO.cjs.map +1 -1
  45. package/_cjs/IO/api/bracketExit.cjs +1 -3
  46. package/_cjs/IO/api/bracketExit.cjs.map +1 -1
  47. package/_cjs/IO/api/clockWith.cjs +1 -1
  48. package/_cjs/IO/api/concurrency.cjs +1 -1
  49. package/_cjs/IO/api/consoleWith.cjs +1 -1
  50. package/_cjs/IO/api/daemonChildren.cjs +19 -0
  51. package/_cjs/IO/api/daemonChildren.cjs.map +1 -0
  52. package/_cjs/IO/api/disconnect.cjs +31 -0
  53. package/_cjs/IO/api/disconnect.cjs.map +1 -0
  54. package/_cjs/IO/api/environment.cjs +1 -1
  55. package/_cjs/IO/api/foreachConcurrent.cjs +19 -20
  56. package/_cjs/IO/api/foreachConcurrent.cjs.map +1 -1
  57. package/_cjs/IO/api/fork.cjs +8 -3
  58. package/_cjs/IO/api/fork.cjs.map +1 -1
  59. package/_cjs/IO/api/forkDaemon.cjs +21 -0
  60. package/_cjs/IO/api/forkDaemon.cjs.map +1 -0
  61. package/_cjs/IO/api/forkIn.cjs +2 -4
  62. package/_cjs/IO/api/forkIn.cjs.map +1 -1
  63. package/_cjs/IO/api/forkScoped.cjs +2 -4
  64. package/_cjs/IO/api/forkScoped.cjs.map +1 -1
  65. package/_cjs/IO/api/fulfill.cjs +1 -3
  66. package/_cjs/IO/api/fulfill.cjs.map +1 -1
  67. package/_cjs/IO/api/interrupt.cjs +8 -59
  68. package/_cjs/IO/api/interrupt.cjs.map +1 -1
  69. package/_cjs/IO/api/race.cjs +24 -12
  70. package/_cjs/IO/api/race.cjs.map +1 -1
  71. package/_cjs/IO/api/{core-scope.cjs → raceWith.cjs} +15 -56
  72. package/_cjs/IO/api/raceWith.cjs.map +1 -0
  73. package/_cjs/IO/api/randomWith.cjs +1 -1
  74. package/_cjs/IO/api/supervised.cjs +1 -1
  75. package/_cjs/IO/api/transplant.cjs +31 -0
  76. package/_cjs/IO/api/transplant.cjs.map +1 -0
  77. package/_cjs/IO/api/whenFiberRef.cjs +20 -0
  78. package/_cjs/IO/api/whenFiberRef.cjs.map +1 -0
  79. package/_cjs/IO/api/whenRef.cjs +21 -0
  80. package/_cjs/IO/api/whenRef.cjs.map +1 -0
  81. package/_cjs/IO/api/zipConcurrent.cjs +25 -19
  82. package/_cjs/IO/api/zipConcurrent.cjs.map +1 -1
  83. package/_cjs/IO/api.cjs +21 -5
  84. package/_cjs/IO/api.cjs.map +1 -1
  85. package/_cjs/IO.cjs +70 -4
  86. package/_cjs/IO.cjs.map +1 -1
  87. package/_cjs/Layer/MemoMap.cjs +1 -3
  88. package/_cjs/Layer/MemoMap.cjs.map +1 -1
  89. package/_cjs/RefSubject/Atomic.cjs +2 -2
  90. package/_cjs/RefSubject/Atomic.cjs.map +1 -1
  91. package/_cjs/Reloadable/constructors.cjs +1 -1
  92. package/_cjs/Reloadable/definition.cjs +1 -1
  93. package/_cjs/STM/api/atomically.cjs +2 -4
  94. package/_cjs/STM/api/atomically.cjs.map +1 -1
  95. package/_cjs/ScopedRef/api.cjs +2 -6
  96. package/_cjs/ScopedRef/api.cjs.map +1 -1
  97. package/_cjs/State/api.cjs +1 -1
  98. package/_cjs/Stream/api.cjs +137 -135
  99. package/_cjs/Stream/api.cjs.map +1 -1
  100. package/_cjs/TReentrantLock/api.cjs +2 -6
  101. package/_cjs/TReentrantLock/api.cjs.map +1 -1
  102. package/_cjs/TSemaphore/api.cjs +1 -3
  103. package/_cjs/TSemaphore/api.cjs.map +1 -1
  104. package/_mjs/Cached/api.mjs +1 -1
  105. package/_mjs/Channel/api/mergeAllWith.mjs +1 -1
  106. package/_mjs/Channel/api/mergeWith.mjs +17 -16
  107. package/_mjs/Channel/api/mergeWith.mjs.map +1 -1
  108. package/_mjs/Channel/api.mjs +1 -3
  109. package/_mjs/Channel/api.mjs.map +1 -1
  110. package/_mjs/Fiber/FiberRuntime.mjs +16 -17
  111. package/_mjs/Fiber/FiberRuntime.mjs.map +1 -1
  112. package/_mjs/FiberRef/api/locallyScoped.mjs +1 -1
  113. package/_mjs/FiberRef/api/locallyScopedWith.mjs +1 -1
  114. package/_mjs/FiberRef/api.mjs +0 -107
  115. package/_mjs/FiberRef/api.mjs.map +1 -1
  116. package/_mjs/FiberRef/constructors.mjs +1 -1
  117. package/_mjs/FiberRef/operations.mjs +109 -0
  118. package/_mjs/FiberRef/operations.mjs.map +1 -0
  119. package/_mjs/FiberRef.mjs +1 -0
  120. package/_mjs/FiberRef.mjs.map +1 -1
  121. package/_mjs/FiberRefs/api.mjs +89 -0
  122. package/_mjs/FiberRefs/api.mjs.map +1 -1
  123. package/_mjs/FiberRefs.mjs +0 -1
  124. package/_mjs/FiberRefs.mjs.map +1 -1
  125. package/_mjs/Future/api.mjs +1 -3
  126. package/_mjs/Future/api.mjs.map +1 -1
  127. package/_mjs/IO/api/asyncIO.mjs +1 -3
  128. package/_mjs/IO/api/asyncIO.mjs.map +1 -1
  129. package/_mjs/IO/api/bracketExit.mjs +1 -3
  130. package/_mjs/IO/api/bracketExit.mjs.map +1 -1
  131. package/_mjs/IO/api/clockWith.mjs +1 -1
  132. package/_mjs/IO/api/concurrency.mjs +1 -1
  133. package/_mjs/IO/api/consoleWith.mjs +1 -1
  134. package/_mjs/IO/api/daemonChildren.mjs +11 -0
  135. package/_mjs/IO/api/daemonChildren.mjs.map +1 -0
  136. package/_mjs/IO/api/disconnect.mjs +23 -0
  137. package/_mjs/IO/api/disconnect.mjs.map +1 -0
  138. package/_mjs/IO/api/environment.mjs +1 -1
  139. package/_mjs/IO/api/foreachConcurrent.mjs +19 -20
  140. package/_mjs/IO/api/foreachConcurrent.mjs.map +1 -1
  141. package/_mjs/IO/api/fork.mjs +6 -2
  142. package/_mjs/IO/api/fork.mjs.map +1 -1
  143. package/_mjs/IO/api/forkDaemon.mjs +13 -0
  144. package/_mjs/IO/api/forkDaemon.mjs.map +1 -0
  145. package/_mjs/IO/api/forkIn.mjs +2 -4
  146. package/_mjs/IO/api/forkIn.mjs.map +1 -1
  147. package/_mjs/IO/api/forkScoped.mjs +2 -4
  148. package/_mjs/IO/api/forkScoped.mjs.map +1 -1
  149. package/_mjs/IO/api/fulfill.mjs +1 -3
  150. package/_mjs/IO/api/fulfill.mjs.map +1 -1
  151. package/_mjs/IO/api/interrupt.mjs +6 -55
  152. package/_mjs/IO/api/interrupt.mjs.map +1 -1
  153. package/_mjs/IO/api/race.mjs +22 -12
  154. package/_mjs/IO/api/race.mjs.map +1 -1
  155. package/_mjs/IO/api/raceWith.mjs +59 -0
  156. package/_mjs/IO/api/raceWith.mjs.map +1 -0
  157. package/_mjs/IO/api/randomWith.mjs +1 -1
  158. package/_mjs/IO/api/supervised.mjs +1 -1
  159. package/_mjs/IO/api/transplant.mjs +23 -0
  160. package/_mjs/IO/api/transplant.mjs.map +1 -0
  161. package/_mjs/IO/api/whenFiberRef.mjs +12 -0
  162. package/_mjs/IO/api/whenFiberRef.mjs.map +1 -0
  163. package/_mjs/IO/api/whenRef.mjs +13 -0
  164. package/_mjs/IO/api/whenRef.mjs.map +1 -0
  165. package/_mjs/IO/api/zipConcurrent.mjs +23 -17
  166. package/_mjs/IO/api/zipConcurrent.mjs.map +1 -1
  167. package/_mjs/IO/api.mjs +16 -3
  168. package/_mjs/IO/api.mjs.map +1 -1
  169. package/_mjs/IO.mjs +7 -1
  170. package/_mjs/IO.mjs.map +1 -1
  171. package/_mjs/Layer/MemoMap.mjs +1 -3
  172. package/_mjs/Layer/MemoMap.mjs.map +1 -1
  173. package/_mjs/RefSubject/Atomic.mjs +1 -1
  174. package/_mjs/RefSubject/Atomic.mjs.map +1 -1
  175. package/_mjs/Reloadable/constructors.mjs +1 -1
  176. package/_mjs/Reloadable/definition.mjs +1 -1
  177. package/_mjs/STM/api/atomically.mjs +2 -4
  178. package/_mjs/STM/api/atomically.mjs.map +1 -1
  179. package/_mjs/ScopedRef/api.mjs +2 -6
  180. package/_mjs/ScopedRef/api.mjs.map +1 -1
  181. package/_mjs/State/api.mjs +1 -1
  182. package/_mjs/Stream/api.mjs +137 -135
  183. package/_mjs/Stream/api.mjs.map +1 -1
  184. package/_mjs/TReentrantLock/api.mjs +2 -6
  185. package/_mjs/TReentrantLock/api.mjs.map +1 -1
  186. package/_mjs/TSemaphore/api.mjs +1 -3
  187. package/_mjs/TSemaphore/api.mjs.map +1 -1
  188. package/_src/Channel/api.ts +1 -1
  189. package/_src/FiberRef/api.ts +0 -114
  190. package/_src/FiberRef/operations.ts +115 -0
  191. package/_src/FiberRef.ts +1 -0
  192. package/_src/FiberRefs/api.ts +72 -0
  193. package/_src/FiberRefs.ts +0 -1
  194. package/_src/Future/api.ts +1 -1
  195. package/_src/IO/api/asyncIO.ts +1 -1
  196. package/_src/IO/api/bracketExit.ts +1 -1
  197. package/_src/IO/api/daemonChildren.ts +6 -0
  198. package/_src/IO/api/disconnect.ts +25 -0
  199. package/_src/IO/api/foreachConcurrent.ts +1 -1
  200. package/_src/IO/api/fork.ts +3 -0
  201. package/_src/IO/api/forkDaemon.ts +12 -0
  202. package/_src/IO/api/forkIn.ts +1 -1
  203. package/_src/IO/api/forkScoped.ts +1 -3
  204. package/_src/IO/api/fulfill.ts +1 -1
  205. package/_src/IO/api/interrupt.ts +5 -56
  206. package/_src/IO/api/race.ts +18 -8
  207. package/_src/IO/api/{core-scope.ts → raceWith.ts} +2 -44
  208. package/_src/IO/api/transplant.ts +19 -0
  209. package/_src/IO/api/whenFiberRef.ts +9 -0
  210. package/_src/IO/api/whenRef.ts +9 -0
  211. package/_src/IO/api/zipConcurrent.ts +41 -43
  212. package/_src/IO/api.ts +18 -2
  213. package/_src/IO.ts +7 -1
  214. package/_src/Layer/MemoMap.ts +1 -1
  215. package/_src/RefSubject/Atomic.ts +1 -1
  216. package/_src/STM/api/atomically.ts +1 -1
  217. package/_src/ScopedRef/api.ts +2 -2
  218. package/_src/TReentrantLock/api.ts +2 -2
  219. package/_src/TSemaphore/api.ts +1 -1
  220. package/package.json +2 -2
  221. package/FiberRefs/join.d.ts +0 -9
  222. package/IO/api/core-scope.d.ts +0 -43
  223. package/_cjs/FiberRefs/join.cjs +0 -104
  224. package/_cjs/FiberRefs/join.cjs.map +0 -1
  225. package/_cjs/IO/api/core-scope.cjs.map +0 -1
  226. package/_mjs/FiberRefs/join.mjs +0 -96
  227. package/_mjs/FiberRefs/join.mjs.map +0 -1
  228. package/_mjs/IO/api/core-scope.mjs +0 -97
  229. package/_mjs/IO/api/core-scope.mjs.map +0 -1
  230. package/_src/FiberRefs/join.ts +0 -71
@@ -0,0 +1,115 @@
1
+ import { concrete } from "@fncts/io/FiberRef/definition";
2
+
3
+ /**
4
+ * @tsplus pipeable fncts.io.FiberRef modify
5
+ */
6
+ export function modify<A, B>(f: (a: A) => readonly [B, A], __tsplusTrace?: string) {
7
+ return (self: FiberRef<A>): UIO<B> => {
8
+ concrete(self);
9
+ return IO.withFiberRuntime((fiber) =>
10
+ IO(() => {
11
+ const [result, newValue] = f(fiber.getFiberRef(self));
12
+ fiber.setFiberRef(self, newValue);
13
+ return result;
14
+ }),
15
+ );
16
+ };
17
+ }
18
+
19
+ /**
20
+ * @tsplus pipeable fncts.io.FiberRef update
21
+ */
22
+ export function update<A>(f: (a: A) => A, __tsplusTrace?: string) {
23
+ return (fiberRef: FiberRef<A>): UIO<void> => {
24
+ return fiberRef.modify((a) => [undefined, f(a)]);
25
+ };
26
+ }
27
+
28
+ /**
29
+ * @tsplus pipeable fncts.io.FiberRef set
30
+ */
31
+ export function set<A>(a: A, __tsplusTrace?: string) {
32
+ return (fiberRef: FiberRef<A>): UIO<void> => {
33
+ return fiberRef.modify(() => [undefined, a]);
34
+ };
35
+ }
36
+
37
+ /**
38
+ * @tsplus getter fncts.io.FiberRef get
39
+ */
40
+ export function get<A>(fiberRef: FiberRef<A>, __tsplusTrace?: string): UIO<A> {
41
+ return fiberRef.modify((a) => [a, a]);
42
+ }
43
+
44
+ /**
45
+ * @tsplus pipeable fncts.io.FiberRef getAndSet
46
+ */
47
+ export function getAndSet<A>(a: A, __tsplusTrace?: string) {
48
+ return (fiberRef: FiberRef<A>): UIO<A> => {
49
+ return fiberRef.modify((v) => [v, a]);
50
+ };
51
+ }
52
+
53
+ /**
54
+ * @tsplus pipeable fncts.io.FiberRef getAndUpdate
55
+ */
56
+ export function getAndUpdate<A>(f: (a: A) => A, __tsplusTrace?: string) {
57
+ return (fiberRef: FiberRef<A>): UIO<A> => {
58
+ return fiberRef.modify((a) => [a, f(a)]);
59
+ };
60
+ }
61
+
62
+ /**
63
+ * @tsplus pipeable fncts.io.FiberRef getAndUpdateJust
64
+ */
65
+ export function getAndUpdateJust<A>(f: (a: A) => Maybe<A>, __tsplusTrace?: string) {
66
+ return (fiberRef: FiberRef<A>): UIO<A> => {
67
+ return fiberRef.modify((a) => [a, f(a).getOrElse(a)]);
68
+ };
69
+ }
70
+
71
+ /**
72
+ * Returns an `IO` that runs with `value` bound to the current fiber.
73
+ *
74
+ * Guarantees that fiber data is properly restored via `bracket`.
75
+ *
76
+ * @tsplus fluent fncts.io.FiberRef locally
77
+ */
78
+ export function locally<A>(fiberRef: FiberRef<A>, value: A, __tsplusTrace?: string) {
79
+ return <R1, E1, B>(use: IO<R1, E1, B>): IO<R1, E1, B> =>
80
+ IO.withFiberRuntime((fiberState) => {
81
+ const oldValue = fiberState.getFiberRef(fiberRef);
82
+ fiberState.setFiberRef(fiberRef, value);
83
+ return use.ensuring(IO.succeed(fiberState.setFiberRef(fiberRef, oldValue)));
84
+ });
85
+ }
86
+
87
+ /**
88
+ * Returns an `IO` that runs with `f` applied to the current fiber.
89
+ *
90
+ * Guarantees that fiber data is properly restored via `bracket`.
91
+ *
92
+ * @tsplus fluent fncts.io.FiberRef locallyWith
93
+ */
94
+ export function locallyWith<A>(self: FiberRef<A>, f: (a: A) => A, __tsplusTrace?: string) {
95
+ return <R1, E1, B>(use: IO<R1, E1, B>): IO<R1, E1, B> => self.getWith((a) => self.locally(f(a))(use));
96
+ }
97
+
98
+ /**
99
+ * @tsplus pipeable fncts.io.FiberRef getWith
100
+ */
101
+ export function getWith<A, R, E, B>(f: (a: A) => IO<R, E, B>, __tsplusTrace?: string) {
102
+ return (fiberRef: FiberRef<A>): IO<R, E, B> => {
103
+ return fiberRef.get.flatMap(f);
104
+ };
105
+ }
106
+
107
+ /**
108
+ * @tsplus getter fncts.io.FiberRef remove
109
+ */
110
+ export function remove<A>(self: FiberRef<A>, __tsplusTrace?: string): UIO<void> {
111
+ return IO.withFiberRuntime((fiberState) => {
112
+ fiberState.deleteFiberRef(self);
113
+ return IO.unit;
114
+ });
115
+ }
package/_src/FiberRef.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  export * from "./FiberRef/api.js";
3
3
  export * from "./FiberRef/constructors.js";
4
4
  export * from "./FiberRef/definition.js";
5
+ export * from "./FiberRef/operations.js";
5
6
  export * from "./FiberRef/unsafe.js";
6
7
  // codegen:end
7
8
  // codegen:start { preset: barrel, include: ./FiberRef/api/*.ts }
@@ -84,3 +84,75 @@ export function remove(self: FiberRefs, fiberRef: FiberRef<any>): FiberRefs {
84
84
  export function unFiberRefs(self: FiberRefs): HashMap<FiberRef<any>, Cons<readonly [FiberId.Runtime, unknown]>> {
85
85
  return FiberRefs.reverseGet(self);
86
86
  }
87
+
88
+ /**
89
+ * @tsplus pipeable fncts.io.FiberRefs join
90
+ */
91
+ export function join(fiberId: FiberId.Runtime, that: FiberRefs) {
92
+ return (self: FiberRefs): FiberRefs => {
93
+ const parentFiberRefs = FiberRefs.reverseGet(self);
94
+ const childFiberRefs = FiberRefs.reverseGet(that);
95
+ const fiberRefLocals = childFiberRefs.foldLeftWithIndex(parentFiberRefs, (ref, parentFiberRefs, childStack) => {
96
+ const childValue = childStack.head[1];
97
+ if (childStack.head[0] == fiberId) {
98
+ return parentFiberRefs;
99
+ }
100
+ return parentFiberRefs.get(ref).match(
101
+ () => {
102
+ if (Equatable.strictEquals(childValue, ref.initial)) return parentFiberRefs;
103
+ return parentFiberRefs.set(ref, Cons([fiberId, childValue] as const));
104
+ },
105
+ (parentStack) => {
106
+ const [ancestor, wasModified] = findAncestor(ref, parentStack, childStack);
107
+ if (!wasModified) return parentFiberRefs;
108
+ const patch = ref.diff(ancestor, childValue);
109
+ const oldValue = parentStack.head[1];
110
+ const newValue = ref.join(oldValue, ref.patch(patch)(oldValue));
111
+ if (oldValue === newValue) return parentFiberRefs;
112
+ let newStack: Cons<readonly [FiberId.Runtime, unknown]>;
113
+ if (parentStack.isEmpty()) {
114
+ newStack = Cons([fiberId, newValue] as const);
115
+ } else {
116
+ const [parentFiberId] = parentStack.head;
117
+ if (parentFiberId == fiberId) {
118
+ newStack = Cons([parentFiberId, newValue], parentStack.tail);
119
+ } else {
120
+ newStack = Cons([fiberId, newValue], parentStack);
121
+ }
122
+ }
123
+ return parentFiberRefs.set(ref, newStack);
124
+ },
125
+ );
126
+ });
127
+ return FiberRefs.get(fiberRefLocals);
128
+ };
129
+ }
130
+
131
+ function compareFiberId(left: FiberId.Runtime, right: FiberId.Runtime): number {
132
+ const compare = Number.Ord.compare(right.startTime)(left.startTime);
133
+ return compare === 0 ? Number.Ord.compare(right.id)(left.id) : compare;
134
+ }
135
+
136
+ /**
137
+ * @tsplus tailRec
138
+ */
139
+ function findAncestor(
140
+ ref: FiberRef<any>,
141
+ parentStack: List<readonly [FiberId.Runtime, any]>,
142
+ childStack: List<readonly [FiberId.Runtime, any]>,
143
+ childModified = false,
144
+ ): readonly [any, boolean] {
145
+ if (parentStack.isNonEmpty() && childStack.isNonEmpty()) {
146
+ const [parentFiberId] = parentStack.head;
147
+ const [childFiberId, childValue] = childStack.head;
148
+ const compare = compareFiberId(parentFiberId, childFiberId);
149
+ if (compare < 0) {
150
+ return findAncestor(ref, parentStack, childStack.tail, true);
151
+ } else if (compare > 0) {
152
+ return findAncestor(ref, parentStack.tail, childStack, childModified);
153
+ } else {
154
+ return [childValue, childModified];
155
+ }
156
+ }
157
+ return [ref.initial, true];
158
+ }
package/_src/FiberRefs.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  // codegen:start { preset: barrel, include: ./FiberRefs/*.ts }
2
2
  export * from "./FiberRefs/api.js";
3
3
  export * from "./FiberRefs/definition.js";
4
- export * from "./FiberRefs/join.js";
5
4
  // codegen:end
@@ -49,7 +49,7 @@ export function failCause<E>(cause: Cause<E>, __tsplusTrace?: string) {
49
49
  */
50
50
  export function fulfill<R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string) {
51
51
  return (future: Future<E, A>): IO<R, never, boolean> => {
52
- return IO.uninterruptibleMask(({ restore }) => restore(io).result.flatMap((exit) => future.done(exit)));
52
+ return IO.uninterruptibleMask((restore) => restore(io).result.flatMap((exit) => future.done(exit)));
53
53
  };
54
54
  }
55
55
 
@@ -9,7 +9,7 @@ export function asyncIO<R, E, A>(
9
9
  const f = Δ(Future.make<E, A>());
10
10
  const r = Δ(IO.runtime<R>());
11
11
  const a = Δ(
12
- IO.uninterruptibleMask(({ restore }) => {
12
+ IO.uninterruptibleMask((restore) => {
13
13
  const io = register((k) => r.unsafeRunAsync(k.fulfill(f)));
14
14
  return restore(io.catchAllCause((cause) => f.failCause(cause))).fork > restore(f.await);
15
15
  }),
@@ -14,7 +14,7 @@ export function bracketExit<R, E, A, E1, R1, A1, R2, E2>(
14
14
  release: (a: A, e: Exit<E1, A1>) => IO<R2, E2, any>,
15
15
  __tsplusTrace?: string,
16
16
  ): IO<R | R1 | R2, E | E1 | E2, A1> {
17
- return IO.uninterruptibleMask(({ restore }) =>
17
+ return IO.uninterruptibleMask((restore) =>
18
18
  acquire().flatMap((a) =>
19
19
  IO.defer(restore(use(a))).result.flatMap((exit) =>
20
20
  IO.defer(release(a, exit)).matchCauseIO(
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @tsplus getter fncts.io.IO daemonChildren
3
+ */
4
+ export function daemonChildren<R, E, A>(self: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
5
+ return FiberRef.forkScopeOverride.locally(Just(FiberScope.global))(self);
6
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Returns an IO whose interruption will be disconnected from the
3
+ * fiber's own interruption, being performed in the background without
4
+ * slowing down the fiber's interruption.
5
+ *
6
+ * This method is useful to create "fast interrupting" effects. For
7
+ * example, if you call this on a bracketed effect, then even if the
8
+ * effect is "stuck" in acquire or release, its interruption will return
9
+ * immediately, while the acquire / release are performed in the
10
+ * background.
11
+ *
12
+ * See timeout and race for other applications.
13
+ *
14
+ * @tsplus getter fncts.io.IO disconnect
15
+ */
16
+ export function disconnect<R, E, A>(self: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
17
+ return IO.uninterruptibleMask((restore) =>
18
+ IO.fiberId.flatMap((fiberId) =>
19
+ Do((Δ) => {
20
+ const fiber = Δ(restore(self).forkDaemon);
21
+ return Δ(restore(fiber.join).onInterrupt(fiber.interruptAsFork(fiberId)));
22
+ }),
23
+ ),
24
+ );
25
+ }
@@ -62,7 +62,7 @@ function foreachConcurrentUnboundedDiscard<R, E, A>(
62
62
  if (size === 0) {
63
63
  return IO.unit;
64
64
  }
65
- return IO.uninterruptibleMask(({ restore }) => {
65
+ return IO.uninterruptibleMask((restore) => {
66
66
  const future = Future.unsafeMake<void, void>(FiberId.none);
67
67
  const ref = new AtomicNumber(0);
68
68
  return IO.transplant((graft) =>
@@ -55,6 +55,9 @@ export function unsafeFork<R, E, A, E1, B>(
55
55
  return fiber;
56
56
  }
57
57
 
58
+ /**
59
+ * @tsplus static fncts.io.IOOps unsafeMakeChildFiber
60
+ */
58
61
  export function unsafeMakeChildFiber<R, E, A, E1, B>(
59
62
  effect: IO<R, E, A>,
60
63
  parentFiber: FiberRuntime<E1, B>,
@@ -0,0 +1,12 @@
1
+ import type { FiberRuntime } from "@fncts/io/Fiber/FiberRuntime";
2
+
3
+ /**
4
+ * Forks the effect into a new fiber attached to the global scope. Because the
5
+ * new fiber is attached to the global scope, when the fiber executing the
6
+ * returned effect terminates, the forked fiber will continue running.
7
+ *
8
+ * @tsplus getter fncts.io.IO forkDaemon
9
+ */
10
+ export function forkDaemon<R, E, A>(ma: IO<R, E, A>, __tsplusTrace?: string): URIO<R, FiberRuntime<E, A>> {
11
+ return ma.fork.daemonChildren;
12
+ }
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export function forkIn(scope: Scope, __tsplusTrace?: string) {
8
8
  return <R, E, A>(self: IO<R, E, A>): URIO<R, Fiber.Runtime<E, A>> => {
9
- return IO.uninterruptibleMask(({ restore }) =>
9
+ return IO.uninterruptibleMask((restore) =>
10
10
  restore(self).forkDaemon.tap((fiber) => scope.addFinalizer(fiber.interrupt)),
11
11
  );
12
12
  };
@@ -5,7 +5,5 @@ export function forkScoped<R, E, A>(
5
5
  self: IO<R, E, A>,
6
6
  __tsplusTrace?: string,
7
7
  ): IO<R | Scope, never, Fiber.Runtime<E, A>> {
8
- return IO.uninterruptibleMask(({ restore }) =>
9
- restore(self).forkDaemon.tap((fiber) => IO.addFinalizer(fiber.interrupt)),
10
- );
8
+ return IO.uninterruptibleMask((restore) => restore(self).forkDaemon.tap((fiber) => IO.addFinalizer(fiber.interrupt)));
11
9
  }
@@ -7,6 +7,6 @@
7
7
  */
8
8
  export function fulfill<E, A>(p: Future<E, A>, __tsplusTrace?: string) {
9
9
  return <R>(effect: IO<R, E, A>): IO<R, never, boolean> => {
10
- return IO.uninterruptibleMask(({ restore }) => restore(effect).result.flatMap((exit) => p.done(exit)));
10
+ return IO.uninterruptibleMask((restore) => restore(effect).result.flatMap((exit) => p.done(exit)));
11
11
  };
12
12
  }
@@ -2,20 +2,11 @@ import { Dynamic, Interruptible, Uninterruptible } from "@fncts/io/IO/definition
2
2
  import { RuntimeFlag } from "@fncts/io/RuntimeFlag";
3
3
  import { RuntimeFlags } from "@fncts/io/RuntimeFlags";
4
4
 
5
- export interface InterruptibilityRestorer {
6
- readonly restore: <R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string) => IO<R, E, A>;
7
- readonly force: <R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string) => IO<R, E, A>;
8
- }
5
+ export type InterruptibilityRestorer = <R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string) => IO<R, E, A>;
9
6
 
10
- const RestoreInterruptible: InterruptibilityRestorer = {
11
- restore: (io, __tsplusTrace) => io.interruptible,
12
- force: (io, __tsplusTrace) => io.interruptible,
13
- };
7
+ const RestoreInterruptible: InterruptibilityRestorer = (io, __tsplusTrace) => io.interruptible;
14
8
 
15
- const RestoreUninterruptible: InterruptibilityRestorer = {
16
- restore: (io, __tsplusTrace) => io.uninterruptible,
17
- force: (io, __tsplusTrace) => io.uninterruptible.disconnect.interruptible,
18
- };
9
+ const RestoreUninterruptible: InterruptibilityRestorer = (io, __tsplusTrace) => io.uninterruptible;
19
10
 
20
11
  /**
21
12
  * Returns an effect that is interrupted as if by the specified fiber.
@@ -34,22 +25,6 @@ export function interruptAs(fiberId: FiberId, __tsplusTrace?: string): FIO<never
34
25
  */
35
26
  export const interrupt: IO<never, never, never> = IO.fiberId.flatMap(IO.interruptAs);
36
27
 
37
- // /**
38
- // * Switches the interrupt status for this effect. If `true` is used, then the
39
- // * effect becomes interruptible (the default), while if `false` is used, then
40
- // * the effect becomes uninterruptible. These changes are compositional, so
41
- // * they only affect regions of the effect.
42
- // *
43
- // * @tsplus fluent fncts.io.IO setInterruptStatus
44
- // */
45
- // export function setInterruptStatus_<R, E, A>(
46
- // self: IO<R, E, A>,
47
- // flag: InterruptStatus,
48
- // __tsplusTrace?: string,
49
- // ): IO<R, E, A> {
50
- // return new SetInterrupt(self, flag, __tsplusTrace);
51
- // }
52
-
53
28
  /**
54
29
  * Returns a new effect that performs the same operations as this effect, but
55
30
  * interruptibly, even if composed inside of an uninterruptible region.
@@ -101,7 +76,7 @@ export function uninterruptibleMask<R, E, A>(f: (restore: InterruptibilityRestor
101
76
  */
102
77
  export function ensuring<R1>(finalizer: IO<R1, never, any>, __tsplusTrace?: string) {
103
78
  return <R, E, A>(self: IO<R, E, A>): IO<R | R1, E, A> => {
104
- return IO.uninterruptibleMask(({ restore }) =>
79
+ return IO.uninterruptibleMask((restore) =>
105
80
  restore(self).matchCauseIO(
106
81
  (cause1) =>
107
82
  finalizer.matchCauseIO(
@@ -172,7 +147,7 @@ export function onInterruptWith<R1, E1>(
172
147
  */
173
148
  export function onExit<E, A, R1, E1>(cleanup: (exit: Exit<E, A>) => IO<R1, E1, any>, __tsplusTrace?: string) {
174
149
  return <R>(self: IO<R, E, A>): IO<R | R1, E | E1, A> => {
175
- return IO.uninterruptibleMask(({ restore }) =>
150
+ return IO.uninterruptibleMask((restore) =>
176
151
  restore(self).matchCauseIO(
177
152
  (failure1) => {
178
153
  const result = Exit.failCause(failure1);
@@ -189,29 +164,3 @@ export function onExit<E, A, R1, E1>(cleanup: (exit: Exit<E, A>) => IO<R1, E1, a
189
164
  );
190
165
  };
191
166
  }
192
-
193
- /**
194
- * Returns an IO whose interruption will be disconnected from the
195
- * fiber's own interruption, being performed in the background without
196
- * slowing down the fiber's interruption.
197
- *
198
- * This method is useful to create "fast interrupting" effects. For
199
- * example, if you call this on a bracketed effect, then even if the
200
- * effect is "stuck" in acquire or release, its interruption will return
201
- * immediately, while the acquire / release are performed in the
202
- * background.
203
- *
204
- * See timeout and race for other applications.
205
- *
206
- * @tsplus getter fncts.io.IO disconnect
207
- */
208
- export function disconnect<R, E, A>(self: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
209
- return uninterruptibleMask(({ restore }) =>
210
- IO.fiberId.flatMap((fiberId) =>
211
- Do((Δ) => {
212
- const fiber = Δ(restore(self).forkDaemon);
213
- return Δ(restore(fiber.join).onInterrupt(fiber.interruptAsFork(fiberId)));
214
- }),
215
- ),
216
- );
217
- }
@@ -1,7 +1,3 @@
1
- function maybeDisconnect<R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
2
- return IO.uninterruptibleMask((restore) => restore.force(io));
3
- }
4
-
5
1
  /**
6
2
  * Returns an IO that races this effect with the specified effect,
7
3
  * returning the first successful `A` from the faster side. If one effect
@@ -14,10 +10,24 @@ function maybeDisconnect<R, E, A>(io: IO<R, E, A>, __tsplusTrace?: string): IO<R
14
10
  * @tsplus pipeable fncts.io.IO race
15
11
  */
16
12
  export function race<R1, E1, A1>(that: IO<R1, E1, A1>) {
17
- return <R, E, A>(io: IO<R, E, A>): IO<R | R1, E | E1, A | A1> => {
18
- return IO.fiberId.flatMap((id) =>
19
- maybeDisconnect(io).raceWith(
20
- maybeDisconnect(that),
13
+ return <R, E, A>(self: IO<R, E, A>): IO<R | R1, E | E1, A | A1> => {
14
+ return IO.checkInterruptible((status) => disconnect(self, status).raceAwait(disconnect(that, status)));
15
+ };
16
+ }
17
+
18
+ function disconnect<R, E, A>(io: IO<R, E, A>, interruptStatus: InterruptStatus, __tsplusTrace?: string): IO<R, E, A> {
19
+ if (interruptStatus.isInterruptible) return io.disconnect;
20
+ else return io.uninterruptible.disconnect.interruptible;
21
+ }
22
+
23
+ /**
24
+ * @tsplus pipeable fncts.io.IO raceAwait
25
+ */
26
+ export function raceAwait<R1, E1, A1>(that: IO<R1, E1, A1>) {
27
+ return <R, E, A>(self: IO<R, E, A>): IO<R | R1, E | E1, A | A1> => {
28
+ return IO.fiberIdWith((id) =>
29
+ self.raceWith(
30
+ that,
21
31
  (exit, right) =>
22
32
  exit.match(
23
33
  (cause) => right.join.mapErrorCause((c) => Cause.both(cause, c)),
@@ -2,17 +2,6 @@ import type { FiberRuntime } from "@fncts/io/Fiber/FiberRuntime";
2
2
 
3
3
  import { ExitTag } from "@fncts/base/data/Exit";
4
4
  import { AtomicBoolean } from "@fncts/base/internal/AtomicBoolean";
5
- import { unsafeMakeChildFiber } from "@fncts/io/IO/api/fork";
6
-
7
- import { FiberScope } from "../../FiberScope.js";
8
- import { IO } from "../definition.js";
9
-
10
- /**
11
- * @tsplus getter fncts.io.IO daemonChildren
12
- */
13
- export function daemonChildren<R, E, A>(self: IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
14
- return FiberRef.forkScopeOverride.locally(Just(FiberScope.global))(self);
15
- }
16
5
 
17
6
  /**
18
7
  * @tsplus pipeable fncts.io.IO raceFibersWith
@@ -40,8 +29,8 @@ export function raceFibersWith<R, E, A, R1, E1, B, R2, E2, C, R3, E3, D>(
40
29
  }
41
30
 
42
31
  const raceIndicator = new AtomicBoolean(true);
43
- const leftFiber = unsafeMakeChildFiber(left, parentState, parentRuntimeFlags, null, __tsplusTrace);
44
- const rightFiber = unsafeMakeChildFiber(right0, parentState, parentRuntimeFlags, null, __tsplusTrace);
32
+ const leftFiber = IO.unsafeMakeChildFiber(left, parentState, parentRuntimeFlags, null, __tsplusTrace);
33
+ const rightFiber = IO.unsafeMakeChildFiber(right0, parentState, parentRuntimeFlags, null, __tsplusTrace);
45
34
  leftFiber.setFiberRef(FiberRef.forkScopeOverride, Just(parentState.scope));
46
35
  rightFiber.setFiberRef(FiberRef.forkScopeOverride, Just(parentState.scope));
47
36
 
@@ -91,34 +80,3 @@ export function raceWith<R, E, A, R1, E1, A1, R2, E2, A2, R3, E3, A3>(
91
80
  );
92
81
  };
93
82
  }
94
-
95
- export type Grafter = <R, E, A>(effect: IO<R, E, A>) => IO<R, E, A>;
96
-
97
- /**
98
- * Transplants specified effects so that when those effects fork other
99
- * effects, the forked effects will be governed by the scope of the
100
- * fiber that executes this effect.
101
- *
102
- * This can be used to "graft" deep grandchildren onto a higher-level
103
- * scope, effectively extending their lifespans into the parent scope.
104
- *
105
- * @tsplus static fncts.io.IOOps transplant
106
- */
107
- export function transplant<R, E, A>(f: (_: Grafter) => IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
108
- return IO.withFiberRuntime((fiberState) => {
109
- const scopeOverride = fiberState.getFiberRef(FiberRef.forkScopeOverride);
110
- const scope = scopeOverride.getOrElse(fiberState.scope);
111
- return f(FiberRef.forkScopeOverride.locally(Just(scope)));
112
- });
113
- }
114
-
115
- /**
116
- * Forks the effect into a new fiber attached to the global scope. Because the
117
- * new fiber is attached to the global scope, when the fiber executing the
118
- * returned effect terminates, the forked fiber will continue running.
119
- *
120
- * @tsplus getter fncts.io.IO forkDaemon
121
- */
122
- export function forkDaemon<R, E, A>(ma: IO<R, E, A>, __tsplusTrace?: string): URIO<R, FiberRuntime<E, A>> {
123
- return ma.fork.daemonChildren;
124
- }
@@ -0,0 +1,19 @@
1
+ export type Grafter = <R, E, A>(effect: IO<R, E, A>) => IO<R, E, A>;
2
+
3
+ /**
4
+ * Transplants specified effects so that when those effects fork other
5
+ * effects, the forked effects will be governed by the scope of the
6
+ * fiber that executes this effect.
7
+ *
8
+ * This can be used to "graft" deep grandchildren onto a higher-level
9
+ * scope, effectively extending their lifespans into the parent scope.
10
+ *
11
+ * @tsplus static fncts.io.IOOps transplant
12
+ */
13
+ export function transplant<R, E, A>(f: (_: Grafter) => IO<R, E, A>, __tsplusTrace?: string): IO<R, E, A> {
14
+ return IO.withFiberRuntime((fiberState) => {
15
+ const scopeOverride = fiberState.getFiberRef(FiberRef.forkScopeOverride);
16
+ const scope = scopeOverride.getOrElse(fiberState.scope);
17
+ return f(FiberRef.forkScopeOverride.locally(Just(scope)));
18
+ });
19
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @tsplus pipeable fncts.io.IO whenFiberRef
3
+ * @tsplus static fncts.io.IOOps whenFiberRef
4
+ */
5
+ export function whenFiberRef<S>(ref: FiberRef<S>, f: Predicate<S>, __tsplusTrace?: string) {
6
+ return <R, E, A>(self: IO<R, E, A>): IO<R, E, Maybe<A>> => {
7
+ return self.whenIO(ref.get.map(f));
8
+ };
9
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @tsplus pipeable fncts.io.IO whenRef
3
+ * @tsplus static fncts.io.IOOps whenRef
4
+ */
5
+ export function whenRef<S>(ref: Ref<S>, f: Predicate<S>) {
6
+ return <R, E, A>(self: IO<R, E, A>): IO<R, E, Maybe<A>> => {
7
+ return self.whenIO(ref.get.map(f));
8
+ };
9
+ }