knitting 0.1.53 → 0.1.55

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 (135) hide show
  1. package/README.md +38 -27
  2. package/knitting.d.ts +797 -5
  3. package/knitting.js +9780 -5
  4. package/map.md +9 -12
  5. package/package.json +14 -13
  6. package/shared-memory.d.ts +155 -0
  7. package/shared-memory.js +1342 -0
  8. package/unsafe.d.ts +71 -1
  9. package/unsafe.js +878 -1
  10. package/utils.d.ts +31 -1
  11. package/utils.js +116 -1
  12. package/process-shared-buffer.d.ts +0 -1
  13. package/process-shared-buffer.js +0 -1
  14. package/src/api.d.ts +0 -69
  15. package/src/api.js +0 -555
  16. package/src/common/envelope.d.ts +0 -17
  17. package/src/common/envelope.js +0 -22
  18. package/src/common/module-url.d.ts +0 -1
  19. package/src/common/module-url.js +0 -24
  20. package/src/common/node-compat.d.ts +0 -20
  21. package/src/common/node-compat.js +0 -24
  22. package/src/common/path-canonical.d.ts +0 -6
  23. package/src/common/path-canonical.js +0 -41
  24. package/src/common/runtime.d.ts +0 -15
  25. package/src/common/runtime.js +0 -91
  26. package/src/common/shared-buffer-region.d.ts +0 -11
  27. package/src/common/shared-buffer-region.js +0 -21
  28. package/src/common/shared-buffer-text.d.ts +0 -16
  29. package/src/common/shared-buffer-text.js +0 -65
  30. package/src/common/task-source.d.ts +0 -3
  31. package/src/common/task-source.js +0 -84
  32. package/src/common/task-symbol.d.ts +0 -1
  33. package/src/common/task-symbol.js +0 -1
  34. package/src/common/with-resolvers.d.ts +0 -9
  35. package/src/common/with-resolvers.js +0 -23
  36. package/src/common/worker-runtime.d.ts +0 -42
  37. package/src/common/worker-runtime.js +0 -61
  38. package/src/connections/buffer-reference-native.d.ts +0 -56
  39. package/src/connections/buffer-reference-native.js +0 -217
  40. package/src/connections/buffer-reference.d.ts +0 -78
  41. package/src/connections/buffer-reference.js +0 -461
  42. package/src/connections/bun.d.ts +0 -22
  43. package/src/connections/bun.js +0 -214
  44. package/src/connections/deno.d.ts +0 -22
  45. package/src/connections/deno.js +0 -205
  46. package/src/connections/file-descriptor.d.ts +0 -39
  47. package/src/connections/file-descriptor.js +0 -161
  48. package/src/connections/index.d.ts +0 -4
  49. package/src/connections/index.js +0 -4
  50. package/src/connections/node-addons.d.ts +0 -5
  51. package/src/connections/node-addons.js +0 -43
  52. package/src/connections/node-buffer-pointer.d.ts +0 -20
  53. package/src/connections/node-buffer-pointer.js +0 -16
  54. package/src/connections/node.d.ts +0 -30
  55. package/src/connections/node.js +0 -62
  56. package/src/connections/posix.d.ts +0 -32
  57. package/src/connections/posix.js +0 -77
  58. package/src/connections/process-shared-buffer.d.ts +0 -75
  59. package/src/connections/process-shared-buffer.js +0 -279
  60. package/src/connections/shared-array-buffer-payload.d.ts +0 -36
  61. package/src/connections/shared-array-buffer-payload.js +0 -235
  62. package/src/connections/types.d.ts +0 -50
  63. package/src/connections/types.js +0 -37
  64. package/src/connections/windows.d.ts +0 -28
  65. package/src/connections/windows.js +0 -224
  66. package/src/debug/env-diff.d.ts +0 -26
  67. package/src/debug/env-diff.js +0 -49
  68. package/src/debug/gate.d.ts +0 -18
  69. package/src/debug/gate.js +0 -69
  70. package/src/debug/handle.d.ts +0 -23
  71. package/src/debug/handle.js +0 -48
  72. package/src/error.d.ts +0 -13
  73. package/src/error.js +0 -49
  74. package/src/ipc/tools/ring-queue.d.ts +0 -33
  75. package/src/ipc/tools/ring-queue.js +0 -159
  76. package/src/ipc/transport/shared-memory.d.ts +0 -23
  77. package/src/ipc/transport/shared-memory.js +0 -35
  78. package/src/memory/byte-carpet.d.ts +0 -73
  79. package/src/memory/byte-carpet.js +0 -157
  80. package/src/memory/lock.d.ts +0 -201
  81. package/src/memory/lock.js +0 -739
  82. package/src/memory/payload-config.d.ts +0 -31
  83. package/src/memory/payload-config.js +0 -67
  84. package/src/memory/payloadCodec.d.ts +0 -46
  85. package/src/memory/payloadCodec.js +0 -1334
  86. package/src/memory/regionRegistry.d.ts +0 -17
  87. package/src/memory/regionRegistry.js +0 -285
  88. package/src/memory/shared-buffer-io.d.ts +0 -55
  89. package/src/memory/shared-buffer-io.js +0 -403
  90. package/src/permission/index.d.ts +0 -2
  91. package/src/permission/index.js +0 -2
  92. package/src/permission/protocol.d.ts +0 -166
  93. package/src/permission/protocol.js +0 -650
  94. package/src/runtime/balancer.d.ts +0 -19
  95. package/src/runtime/balancer.js +0 -149
  96. package/src/runtime/dispatcher.d.ts +0 -34
  97. package/src/runtime/dispatcher.js +0 -142
  98. package/src/runtime/inline-executor.d.ts +0 -10
  99. package/src/runtime/inline-executor.js +0 -282
  100. package/src/runtime/pool.d.ts +0 -30
  101. package/src/runtime/pool.js +0 -391
  102. package/src/runtime/process-worker.d.ts +0 -92
  103. package/src/runtime/process-worker.js +0 -673
  104. package/src/runtime/tx-queue.d.ts +0 -26
  105. package/src/runtime/tx-queue.js +0 -151
  106. package/src/shared/abortSignal.d.ts +0 -23
  107. package/src/shared/abortSignal.js +0 -134
  108. package/src/types.d.ts +0 -346
  109. package/src/types.js +0 -2
  110. package/src/utils/http.d.ts +0 -29
  111. package/src/utils/http.js +0 -100
  112. package/src/worker/bootstrap.d.ts +0 -5
  113. package/src/worker/bootstrap.js +0 -78
  114. package/src/worker/composable-runners.d.ts +0 -12
  115. package/src/worker/composable-runners.js +0 -97
  116. package/src/worker/loop.d.ts +0 -2
  117. package/src/worker/loop.js +0 -382
  118. package/src/worker/process-worker-bootstrap.d.ts +0 -8
  119. package/src/worker/process-worker-bootstrap.js +0 -160
  120. package/src/worker/rx-queue.d.ts +0 -25
  121. package/src/worker/rx-queue.js +0 -173
  122. package/src/worker/safety/index.d.ts +0 -4
  123. package/src/worker/safety/index.js +0 -4
  124. package/src/worker/safety/performance.d.ts +0 -1
  125. package/src/worker/safety/performance.js +0 -17
  126. package/src/worker/safety/process.d.ts +0 -2
  127. package/src/worker/safety/process.js +0 -79
  128. package/src/worker/safety/startup.d.ts +0 -16
  129. package/src/worker/safety/startup.js +0 -30
  130. package/src/worker/safety/worker-data.d.ts +0 -2
  131. package/src/worker/safety/worker-data.js +0 -36
  132. package/src/worker/task-loader.d.ts +0 -27
  133. package/src/worker/task-loader.js +0 -78
  134. package/src/worker/timers.d.ts +0 -18
  135. package/src/worker/timers.js +0 -116
@@ -1,149 +0,0 @@
1
- const selectStrategy = (contexts, handlers, strategy) => {
2
- switch (strategy ?? "roundRobin") {
3
- case "roundRobin":
4
- case "robinRound": // legacy alias
5
- return roundRobin(contexts)(handlers)(handlers.length);
6
- case "firstIdle":
7
- return firstIdle(contexts)(handlers)(handlers.length);
8
- case "randomLane":
9
- return randomLane(contexts)(handlers)(handlers.length);
10
- case "firstIdleOrRandom":
11
- return firstIdleRandom(contexts)(handlers)(handlers.length);
12
- }
13
- // Unreachable code, but guarded for safety.
14
- throw new Error(`Unknown balancer: ${strategy}`);
15
- };
16
- export const managerMethod = ({ contexts, balancer, handlers, inlinerGate, }) => {
17
- const strategy = typeof balancer === "object" && balancer != null
18
- ? balancer.strategy
19
- : balancer;
20
- if (contexts.length < 2) {
21
- throw new Error(contexts.length === 0
22
- ? "No threads available."
23
- : "Cannot rotate with a single thread.");
24
- }
25
- if (handlers.length === 0) {
26
- throw new Error("No handlers provided.");
27
- }
28
- const allInvoker = selectStrategy(contexts, handlers, strategy);
29
- if (!inlinerGate) {
30
- return allInvoker;
31
- }
32
- const inlinerIndex = inlinerGate.index | 0;
33
- const threshold = Number.isFinite(inlinerGate.threshold)
34
- ? Math.max(1, Math.floor(inlinerGate.threshold))
35
- : 1;
36
- if (threshold <= 1 || inlinerIndex < 0 || inlinerIndex >= handlers.length) {
37
- return allInvoker;
38
- }
39
- const workerLaneCount = handlers.length - 1;
40
- if (workerLaneCount <= 0) {
41
- return allInvoker;
42
- }
43
- const workerHandlers = new Array(workerLaneCount);
44
- const workerContexts = new Array(workerLaneCount);
45
- for (let source = 0, lane = 0; source < handlers.length; source += 1) {
46
- if (source === inlinerIndex)
47
- continue;
48
- workerHandlers[lane] = handlers[source];
49
- workerContexts[lane] = contexts[source];
50
- lane += 1;
51
- }
52
- const workerOnlyInvoker = selectStrategy(workerContexts, workerHandlers, strategy);
53
- let inFlight = 0;
54
- const releaseResolved = (value) => {
55
- inFlight -= 1;
56
- return value;
57
- };
58
- const releaseRejected = (error) => {
59
- inFlight -= 1;
60
- throw error;
61
- };
62
- return (args) => {
63
- inFlight += 1;
64
- const invoker = inFlight >= threshold ? allInvoker : workerOnlyInvoker;
65
- try {
66
- return invoker(args).then(releaseResolved, releaseRejected);
67
- }
68
- catch (error) {
69
- inFlight -= 1;
70
- throw error;
71
- }
72
- };
73
- };
74
- export function roundRobin(_contexts) {
75
- return (handlers) => {
76
- return (max) => {
77
- const top = Math.min(max, handlers.length);
78
- if (top <= 1) {
79
- return (args) => handlers[0](args);
80
- }
81
- let rrCursor = 0;
82
- return (args) => {
83
- const lane = rrCursor;
84
- rrCursor += 1;
85
- if (rrCursor === top)
86
- rrCursor = 0;
87
- return handlers[lane](args);
88
- };
89
- };
90
- };
91
- }
92
- export function firstIdle(contexts) {
93
- const isSolved = contexts.map((ctx) => ctx.txIdle);
94
- return (handlers) => {
95
- return (max) => {
96
- const laneCount = Math.min(max, handlers.length);
97
- if (laneCount <= 1) {
98
- return (args) => handlers[0](args);
99
- }
100
- let rrCursor = 0;
101
- return (args) => {
102
- for (let lane = 0; lane < laneCount; lane += 1) {
103
- if (isSolved[lane]()) {
104
- return handlers[lane](args);
105
- }
106
- }
107
- const fallback = rrCursor;
108
- rrCursor += 1;
109
- if (rrCursor === laneCount)
110
- rrCursor = 0;
111
- return handlers[fallback](args);
112
- };
113
- };
114
- };
115
- }
116
- export const randomLane = (_) => {
117
- return (handlers) => {
118
- return (max) => {
119
- const laneCount = Math.min(max, handlers.length);
120
- if (laneCount <= 1) {
121
- return (args) => handlers[0](args);
122
- }
123
- return (args) => {
124
- const lane = (Math.random() * laneCount) | 0;
125
- return handlers[lane](args);
126
- };
127
- };
128
- };
129
- };
130
- export function firstIdleRandom(contexts) {
131
- const isSolved = contexts.map((ctx) => ctx.txIdle);
132
- return (handlers) => {
133
- return (max) => {
134
- const laneCount = Math.min(max, handlers.length);
135
- if (laneCount <= 1) {
136
- return (args) => handlers[0](args);
137
- }
138
- return (args) => {
139
- for (let lane = 0; lane < laneCount; lane += 1) {
140
- if (isSolved[lane]()) {
141
- return handlers[lane](args);
142
- }
143
- }
144
- const fallback = (Math.random() * laneCount) | 0;
145
- return handlers[fallback](args);
146
- };
147
- };
148
- };
149
- }
@@ -1,34 +0,0 @@
1
- import { type MultiQueue } from "./tx-queue.js";
2
- import { type MainSignal } from "../ipc/transport/shared-memory.js";
3
- import { type RuntimeMessageChannelLike, type RuntimeMessagePortLike } from "../common/worker-runtime.js";
4
- import type { DispatcherSettings } from "../types.js";
5
- export declare const hostDispatcherLoop: ({ signalBox: { opView, txStatus, rxStatus, }, queue: { completeFrame, hasPendingFrames, flushToWorker, txIdle, }, channelHandler, dispatcherOptions, notifySignal, }: {
6
- queue: MultiQueue;
7
- signalBox: MainSignal;
8
- channelHandler: ChannelHandler;
9
- dispatcherOptions?: DispatcherSettings;
10
- notifySignal?: () => void;
11
- }) => {
12
- check: {
13
- (): void;
14
- isRunning: boolean;
15
- rerun: boolean;
16
- };
17
- };
18
- export declare class ChannelHandler {
19
- #private;
20
- channel: RuntimeMessageChannelLike;
21
- port1: RuntimeMessagePortLike;
22
- port2: RuntimeMessagePortLike;
23
- constructor();
24
- notify(): void;
25
- /**
26
- * Opens the channel (if not already open) and sets the onmessage handler.
27
- * This is the setup so `notify` can send a message to the port 1.
28
- */
29
- open(f: () => void): void;
30
- /**
31
- * Closes the channel if it is open.
32
- */
33
- close(): void;
34
- }
@@ -1,142 +0,0 @@
1
- import { createRuntimeMessageChannel, } from "../common/worker-runtime.js";
2
- export const hostDispatcherLoop = ({ signalBox: { opView, txStatus, rxStatus, }, queue: { completeFrame, hasPendingFrames, flushToWorker, txIdle, }, channelHandler, dispatcherOptions, notifySignal, }) => {
3
- const a_load = Atomics.load;
4
- const a_store = Atomics.store;
5
- const a_notify = Atomics.notify;
6
- const canNotifySignal = opView.buffer instanceof SharedArrayBuffer;
7
- const wakeSignal = notifySignal ??
8
- (() => {
9
- if (canNotifySignal)
10
- a_notify(opView, 0, 1);
11
- });
12
- const notify = () => channelHandler.notify();
13
- let stallCount = 0 | 0;
14
- const STALL_FREE_LOOPS = Math.max(0, (dispatcherOptions?.stallFreeLoops ?? 128) | 0);
15
- const MAX_BACKOFF_MS = Math.max(0, (dispatcherOptions?.maxBackoffMs ?? 10) | 0);
16
- let backoffTimer;
17
- // inFlight prevents re-entrancy when pool.ts fires check() concurrently
18
- // from both send() and the channel callback. Cheaper than try/finally.
19
- let inFlight = false;
20
- const check = () => {
21
- if (inFlight) {
22
- // Another check() is already mid-drain; mark that a re-run is needed
23
- // so the active invocation loops again before yielding.
24
- check.rerun = true;
25
- return;
26
- }
27
- inFlight = true;
28
- if (backoffTimer !== undefined) {
29
- clearTimeout(backoffTimer);
30
- backoffTimer = undefined;
31
- }
32
- do {
33
- check.rerun = false;
34
- txStatus[0] = 1;
35
- // Wake the worker before draining so it can start processing while we flush.
36
- if (a_load(rxStatus, 0) === 0) {
37
- a_store(opView, 0, 1);
38
- wakeSignal();
39
- }
40
- // Drain loop: local vars so V8 keeps them as unboxed int32.
41
- let anyProgressed = false;
42
- let progressed = true;
43
- while (progressed) {
44
- progressed = false;
45
- if (completeFrame() > 0) {
46
- progressed = true;
47
- anyProgressed = true;
48
- }
49
- while (hasPendingFrames()) {
50
- if (!flushToWorker())
51
- break;
52
- progressed = true;
53
- anyProgressed = true;
54
- }
55
- }
56
- txStatus[0] = 0;
57
- if (!txIdle()) {
58
- if (anyProgressed || hasPendingFrames()) {
59
- stallCount = 0 | 0;
60
- }
61
- else {
62
- stallCount = (stallCount + 1) | 0;
63
- }
64
- inFlight = false;
65
- scheduleNotify();
66
- return;
67
- }
68
- // Queue is fully drained.
69
- stallCount = 0 | 0;
70
- } while (check.rerun);
71
- check.isRunning = false;
72
- inFlight = false;
73
- };
74
- check.isRunning = false;
75
- check.rerun = false;
76
- const scheduleNotify = () => {
77
- if (stallCount <= STALL_FREE_LOOPS) {
78
- notify();
79
- return;
80
- }
81
- // One delayed wakeup at a time; fresh send() calls preempt via check directly.
82
- if (backoffTimer !== undefined)
83
- return;
84
- let delay = (stallCount - STALL_FREE_LOOPS - 1) | 0;
85
- if (delay < 0)
86
- delay = 0;
87
- else if (delay > MAX_BACKOFF_MS)
88
- delay = MAX_BACKOFF_MS;
89
- // Release isRunning during backoff so pool.ts send() can restart the loop.
90
- check.isRunning = false;
91
- backoffTimer = setTimeout(() => {
92
- backoffTimer = undefined;
93
- if (!check.isRunning) {
94
- check.isRunning = true;
95
- check();
96
- }
97
- }, delay);
98
- };
99
- return { check };
100
- };
101
- export class ChannelHandler {
102
- channel;
103
- port1;
104
- port2;
105
- #post2;
106
- constructor() {
107
- this.channel = createRuntimeMessageChannel();
108
- this.port1 = this.channel.port1;
109
- this.port2 = this.channel.port2;
110
- this.#post2 = (message) => this.port2.postMessage(message);
111
- }
112
- notify() {
113
- this.#post2(null);
114
- }
115
- /**
116
- * Opens the channel (if not already open) and sets the onmessage handler.
117
- * This is the setup so `notify` can send a message to the port 1.
118
- */
119
- open(f) {
120
- const port1 = this.port1;
121
- if (typeof port1.on === "function") {
122
- port1.on("message", f);
123
- }
124
- else {
125
- // @ts-ignore
126
- port1.onmessage = f;
127
- }
128
- this.port1.start?.();
129
- this.port2.start?.();
130
- }
131
- /**
132
- * Closes the channel if it is open.
133
- */
134
- close() {
135
- //@ts-ignore
136
- this.port1.onmessage = null;
137
- //@ts-ignore
138
- this.port2.onmessage = null;
139
- this.port1.close?.();
140
- this.port2.close?.();
141
- }
142
- }
@@ -1,10 +0,0 @@
1
- import type { ComposedWithKey, tasks, WorkerCall } from "../types.js";
2
- export declare const createInlineExecutor: ({ tasks, genTaskID, batchSize, }: {
3
- tasks: tasks | ComposedWithKey[];
4
- genTaskID: () => number;
5
- batchSize?: number;
6
- }) => {
7
- readonly kills: () => Promise<void>;
8
- readonly call: ({ fnNumber }: WorkerCall) => (args: unknown) => import("../common/with-resolvers.js").PromiseWithMaybeReject<unknown>;
9
- readonly txIdle: () => boolean;
10
- };
@@ -1,282 +0,0 @@
1
- import { withResolvers } from "../common/with-resolvers.js";
2
- import RingQueue from "../ipc/tools/ring-queue.js";
3
- import { createRuntimeMessageChannel } from "../common/worker-runtime.js";
4
- const normalizeTimeout = (timeout) => {
5
- if (timeout == null)
6
- return undefined;
7
- if (typeof timeout === "number") {
8
- return timeout >= 0
9
- ? { ms: timeout, kind: 0 /* TimeoutKind.Reject */, value: new Error("Task timeout") }
10
- : undefined;
11
- }
12
- const ms = timeout.time;
13
- if (!(ms >= 0))
14
- return undefined;
15
- if ("default" in timeout) {
16
- return { ms, kind: 1 /* TimeoutKind.Resolve */, value: timeout.default };
17
- }
18
- if (timeout.maybe === true) {
19
- return { ms, kind: 1 /* TimeoutKind.Resolve */, value: undefined };
20
- }
21
- if ("error" in timeout) {
22
- return { ms, kind: 0 /* TimeoutKind.Reject */, value: timeout.error };
23
- }
24
- return { ms, kind: 0 /* TimeoutKind.Reject */, value: new Error("Task timeout") };
25
- };
26
- const raceTimeout = (promise, spec) => new Promise((resolve, reject) => {
27
- let done = false;
28
- const timer = setTimeout(() => {
29
- if (done)
30
- return;
31
- done = true;
32
- if (spec.kind === 1 /* TimeoutKind.Resolve */) {
33
- resolve(spec.value);
34
- }
35
- else {
36
- reject(spec.value);
37
- }
38
- }, spec.ms);
39
- promise.then((value) => {
40
- if (done)
41
- return;
42
- done = true;
43
- clearTimeout(timer);
44
- resolve(value);
45
- }, (err) => {
46
- if (done)
47
- return;
48
- done = true;
49
- clearTimeout(timer);
50
- reject(err);
51
- });
52
- });
53
- const INLINE_ABORT_TOOLKIT = (() => {
54
- const hasAborted = () => false;
55
- return {
56
- hasAborted,
57
- };
58
- })();
59
- const composeInlineCallable = (fn, timeout, useAbortToolkit = false) => {
60
- const normalized = normalizeTimeout(timeout);
61
- const run = useAbortToolkit
62
- ? (args) => fn(args, INLINE_ABORT_TOOLKIT)
63
- : fn;
64
- if (!normalized)
65
- return run;
66
- return (args) => {
67
- const result = run(args);
68
- return result instanceof Promise ? raceTimeout(result, normalized) : result;
69
- };
70
- };
71
- export const createInlineExecutor = ({ tasks, genTaskID, batchSize, }) => {
72
- const entries = Array.isArray(tasks)
73
- ? tasks
74
- : Object.values(tasks).sort((a, b) => a.id - b.id);
75
- const runners = entries.map((entry) => {
76
- // Imported tasks must never execute on the host inline lane: their module
77
- // import is meant to stay inside the worker so worker permission policies
78
- // apply. The pool already routes them to worker lanes, but guard here as
79
- // defense in depth so a dispatch regression can't silently import on host.
80
- if (entry.imported === true) {
81
- return () => {
82
- throw new Error("Imported task cannot run on the host inline lane");
83
- };
84
- }
85
- return composeInlineCallable(entry.f, entry.timeout, entry.abortSignal !== undefined);
86
- });
87
- const initCap = 16;
88
- let fnByIndex = new Int32Array(initCap);
89
- let stateByIndex = new Int8Array(initCap).fill(-1 /* SlotStateMacro.Free */);
90
- let argsByIndex = new Array(initCap);
91
- let taskIdByIndex = new Array(initCap).fill(-1);
92
- let deferredByIndex = new Array(initCap);
93
- const freeStack = new Array(initCap);
94
- let freeTop = initCap;
95
- for (let i = 0; i < initCap; i++)
96
- freeStack[i] = initCap - 1 - i;
97
- const pendingQueue = new RingQueue(initCap);
98
- let working = 0;
99
- let isInMacro = false;
100
- let isInMicro = false;
101
- const batchLimit = Number.isFinite(batchSize)
102
- ? Math.max(1, Math.floor(batchSize ?? 1))
103
- : Number.POSITIVE_INFINITY;
104
- const channel = createRuntimeMessageChannel();
105
- const port1 = channel.port1;
106
- const port2 = channel.port2;
107
- const post2 = (message) => port2.postMessage(message);
108
- const hasPending = () => pendingQueue.isEmpty === false;
109
- const queueMicro = typeof queueMicrotask === "function"
110
- ? queueMicrotask
111
- : (callback) => Promise.resolve().then(callback);
112
- const scheduleMacro = () => {
113
- if (working === 0 || isInMacro)
114
- return;
115
- isInMacro = true;
116
- post2(null);
117
- };
118
- const send = () => {
119
- if (working === 0 || isInMacro || isInMicro)
120
- return;
121
- isInMicro = true;
122
- queueMicro(runMicroLoop);
123
- };
124
- const enqueue = (index) => {
125
- pendingQueue.push(index);
126
- send();
127
- };
128
- const enqueueIfCurrent = (index, taskID) => {
129
- if (stateByIndex[index] !== 0 /* SlotStateMacro.Pending */ ||
130
- taskIdByIndex[index] !== taskID)
131
- return;
132
- enqueue(index);
133
- };
134
- const settleIfCurrent = (index, taskID, isError, value) => {
135
- if (stateByIndex[index] !== 0 /* SlotStateMacro.Pending */ ||
136
- taskIdByIndex[index] !== taskID)
137
- return;
138
- const deferred = deferredByIndex[index];
139
- if (deferred) {
140
- if (isError)
141
- deferred.reject(value);
142
- else
143
- deferred.resolve(value);
144
- }
145
- cleanup(index);
146
- };
147
- function allocIndex() {
148
- if (freeTop > 0)
149
- return freeStack[--freeTop];
150
- const oldCap = fnByIndex.length;
151
- const newCap = oldCap << 1;
152
- const nextFnByIndex = new Int32Array(newCap);
153
- nextFnByIndex.set(fnByIndex);
154
- fnByIndex = nextFnByIndex;
155
- const nextStateByIndex = new Int8Array(newCap);
156
- nextStateByIndex.fill(-1 /* SlotStateMacro.Free */);
157
- nextStateByIndex.set(stateByIndex);
158
- stateByIndex = nextStateByIndex;
159
- argsByIndex.length = newCap;
160
- taskIdByIndex.length = newCap;
161
- taskIdByIndex.fill(-1, oldCap);
162
- deferredByIndex.length = newCap;
163
- for (let i = newCap - 1; i >= oldCap; --i) {
164
- freeStack[freeTop++] = i;
165
- }
166
- return freeStack[--freeTop];
167
- }
168
- function processLoop(fromMicro = false) {
169
- let processed = 0;
170
- while (processed < batchLimit) {
171
- const maybeIndex = pendingQueue.shiftNoClear();
172
- if (maybeIndex === undefined)
173
- break;
174
- const index = maybeIndex | 0;
175
- if (stateByIndex[index] !== 0 /* SlotStateMacro.Pending */)
176
- continue;
177
- const taskID = taskIdByIndex[index];
178
- try {
179
- const args = argsByIndex[index];
180
- const fnId = fnByIndex[index];
181
- const res = runners[fnId](args);
182
- if (!(res instanceof Promise)) {
183
- settleIfCurrent(index, taskID, false, res);
184
- processed++;
185
- continue;
186
- }
187
- res.then((value) => settleIfCurrent(index, taskID, false, value), (err) => settleIfCurrent(index, taskID, true, err));
188
- processed++;
189
- }
190
- catch (err) {
191
- settleIfCurrent(index, taskID, true, err);
192
- processed++;
193
- }
194
- }
195
- if (hasPending()) {
196
- if (fromMicro) {
197
- scheduleMacro();
198
- }
199
- else {
200
- post2(null);
201
- }
202
- return;
203
- }
204
- if (!fromMicro) {
205
- isInMacro = false;
206
- }
207
- }
208
- function runMicroLoop() {
209
- if (!isInMicro)
210
- return;
211
- processLoop(true);
212
- isInMicro = false;
213
- }
214
- function cleanup(index) {
215
- working--;
216
- stateByIndex[index] = -1 /* SlotStateMacro.Free */;
217
- fnByIndex[index] = 0;
218
- taskIdByIndex[index] = -1;
219
- argsByIndex[index] = undefined;
220
- deferredByIndex[index] = undefined;
221
- freeStack[freeTop++] = index;
222
- if (working === 0)
223
- isInMacro = false;
224
- }
225
- const call = ({ fnNumber }) => (args) => {
226
- const taskID = genTaskID();
227
- const deferred = withResolvers();
228
- const index = allocIndex();
229
- taskIdByIndex[index] = taskID;
230
- argsByIndex[index] = args;
231
- fnByIndex[index] = fnNumber | 0;
232
- deferredByIndex[index] = deferred;
233
- stateByIndex[index] = 0 /* SlotStateMacro.Pending */;
234
- working++;
235
- if (args instanceof Promise) {
236
- args.then((value) => {
237
- if (taskIdByIndex[index] !== taskID)
238
- return;
239
- argsByIndex[index] = value;
240
- enqueueIfCurrent(index, taskID);
241
- }, (err) => settleIfCurrent(index, taskID, true, err));
242
- }
243
- else {
244
- enqueue(index);
245
- }
246
- return deferred.promise;
247
- };
248
- //@ts-ignore
249
- port1.onmessage = () => processLoop(false);
250
- return {
251
- kills: async () => {
252
- for (let index = 0; index < stateByIndex.length; index++) {
253
- if (stateByIndex[index] !== 0 /* SlotStateMacro.Pending */)
254
- continue;
255
- try {
256
- deferredByIndex[index]?.reject("Thread closed");
257
- }
258
- catch {
259
- }
260
- }
261
- //@ts-ignore
262
- port1.onmessage = null;
263
- port1.close?.();
264
- //@ts-ignore
265
- port2.onmessage = null;
266
- port2.close?.();
267
- pendingQueue.clear();
268
- freeTop = 0;
269
- freeStack.length = 0;
270
- argsByIndex.fill(undefined);
271
- taskIdByIndex.fill(-1);
272
- deferredByIndex.fill(undefined);
273
- fnByIndex.fill(0);
274
- stateByIndex.fill(-1 /* SlotStateMacro.Free */);
275
- working = 0;
276
- isInMacro = false;
277
- isInMicro = false;
278
- },
279
- call,
280
- txIdle: () => working === 0,
281
- };
282
- };
@@ -1,30 +0,0 @@
1
- import { type ProcessSharedMemoryBacking } from "./process-worker.js";
2
- import { type Sab } from "../ipc/transport/shared-memory.js";
3
- import { lock2 } from "../memory/lock.js";
4
- import type { DebugOptions, DispatcherSettings, WorkerContext, WorkerData, WorkerSettings } from "../types.js";
5
- import "../worker/loop.js";
6
- import { type PayloadBufferOptions } from "../memory/payload-config.js";
7
- export declare const spawnWorkerContext: ({ list, ids, names, sab, thread, debug, hostDebug, totalNumberOfThread, source, at, workerOptions, workerExecArgv, permission, host, payload, bufferReferenceReturn, abortSignalCapacity, usesAbortSignal, }: {
8
- list: string[];
9
- ids: number[];
10
- names: string[];
11
- at: number[];
12
- sab?: Sab;
13
- thread: number;
14
- debug?: DebugOptions;
15
- hostDebug?: (message: string) => void;
16
- totalNumberOfThread: number;
17
- source?: string;
18
- workerOptions?: WorkerSettings;
19
- workerExecArgv?: string[];
20
- permission?: WorkerData["permission"];
21
- host?: DispatcherSettings;
22
- payload?: PayloadBufferOptions;
23
- bufferReferenceReturn?: "copy" | "borrow";
24
- abortSignalCapacity?: number;
25
- usesAbortSignal?: boolean;
26
- }) => WorkerContext & {
27
- lock: ReturnType<typeof lock2>;
28
- processSharedMemoryBackings?: readonly ProcessSharedMemoryBacking[];
29
- };
30
- export type CreateContext = WorkerContext;