multithreading
Version:
The missing standard library for multithreading in JavaScript (Works in the browser, Node.js, Deno, Bun).
53 lines (52 loc) • 2.16 kB
JavaScript
// @ts-nocheck This is a polyfill file
/**
* Applies a monkey patch for Atomics.waitAsync specifically for the Deno environment.
* In Deno, the V8 message loop is drained at the start of event loop iterations,
* meaning standard V8 wakeups might not trigger immediate processing of waitAsync.
* This monkey patch injects a setInterval "tick" to ensure the event loop stays active
* and wakes up to process the atomic notification.
*
* waitAsync, along with GC, WeakRef/FinalizationRegistry callbacks and WebAssembly async compilation, are things
* that happen when the V8 message loop is drained. V8 usually expects the message loop to be more or less continuously
* drained, so that the message loop is the event loop, but Deno instead drains the message loop at the beginning of every
* event loop iteration. As such, V8 doesn't have any way to wake up Deno's event loop, and the waitAsync timeout will
* only fire when the event loop is woken up in some other way:
*/
import { setImmediate } from "node:timers";
const originalWaitAsync = Atomics.waitAsync;
// @ts-ignore: Overwriting native function signature
Atomics.waitAsync = function (typedArray, index, value, timeout) {
// Call original
const result = originalWaitAsync(
// @ts-ignore: We simplified the function signature
typedArray, index, value, timeout);
// If sync, return immediately
if (result.async === false) {
return result;
}
// Wrap the promise to keep the loop churning
const originalPromise = result.value;
const wrappedPromise = (async () => {
let active = true;
// Recursive setImmediate keeps the loop active without
// the overhead of the timer heap (calculating milliseconds).
const keepAlive = () => {
if (!active)
return;
setImmediate(keepAlive);
};
// Kick off the loop
keepAlive();
try {
return await originalPromise;
}
finally {
// Stop the loop
active = false;
}
})();
return {
async: true,
value: wrappedPromise,
};
};