node-ejs-renderer/node_modules/memfs/lib/fsa-to-node/worker/SyncMessenger.js

72 lines
2.6 KiB
JavaScript
Raw Permalink Normal View History

2024-06-09 13:55:01 -04:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SyncMessenger = void 0;
/**
* @param condition Condition to wait for, when true, the function returns.
* @param ms Maximum time to wait in milliseconds.
*/
const sleepUntil = (condition, ms = 100) => {
const start = Date.now();
while (!condition()) {
const now = Date.now();
if (now - start > ms)
throw new Error('Timeout');
}
};
/**
* `SyncMessenger` allows to execute asynchronous code synchronously. The
* asynchronous code is executed in a Worker thread, while the main thread is
* blocked until the asynchronous code is finished.
*
* First four 4-byte words is the header, where the first word is used for Atomics
* notifications. The second word is used for spin-locking the main thread until
* the asynchronous code is finished. The third word is used to specify payload
* length. The fourth word is currently unused.
*
* The maximum payload size is the size of the SharedArrayBuffer minus the
* header size.
*/
class SyncMessenger {
constructor(sab) {
this.sab = sab;
this.int32 = new Int32Array(sab);
this.uint8 = new Uint8Array(sab);
this.headerSize = 4 * 4;
this.dataSize = sab.byteLength - this.headerSize;
}
callSync(data) {
const requestLength = data.length;
const headerSize = this.headerSize;
const int32 = this.int32;
int32[1] = 0;
int32[2] = requestLength;
this.uint8.set(data, headerSize);
Atomics.notify(int32, 0);
sleepUntil(() => int32[1] === 1);
const responseLength = int32[2];
const response = this.uint8.slice(headerSize, headerSize + responseLength);
return response;
}
serveAsync(callback) {
const headerSize = this.headerSize;
(async () => {
try {
const int32 = this.int32;
const res = Atomics.wait(int32, 0, 0);
if (res !== 'ok')
throw new Error(`Unexpected Atomics.wait result: ${res}`);
const requestLength = this.int32[2];
const request = this.uint8.slice(headerSize, headerSize + requestLength);
const response = await callback(request);
const responseLength = response.length;
int32[2] = responseLength;
this.uint8.set(response, headerSize);
int32[1] = 1;
}
catch (_a) { }
this.serveAsync(callback);
})().catch(() => { });
}
}
exports.SyncMessenger = SyncMessenger;
//# sourceMappingURL=SyncMessenger.js.map