1+ 'use strict' ;
2+
3+ const { read, write } = require ( 'internal/worker/everysync/objects' ) ;
4+ const {
5+ OFFSET ,
6+ TO_MAIN ,
7+ TO_WORKER ,
8+ } = require ( 'internal/worker/everysync/indexes' ) ;
9+
10+ /**
11+ * Creates a synchronous API facade from a shared memory buffer.
12+ * This function is meant to be used in the main thread to communicate with
13+ * a worker thread that has called `wire()` on the same shared memory.
14+ *
15+ * @param {SharedArrayBuffer } data - The shared memory buffer for communication
16+ * @param {Object } [opts={}] - Options object
17+ * @param {number } [opts.timeout=1000] - Timeout in milliseconds for synchronous operations
18+ * @returns {Object } - An object with methods that match the ones exposed by the worker
19+ */
20+ function makeSync ( data , opts = { } ) {
21+ const timeout = opts . timeout || 1000 ;
22+ const metaView = new Int32Array ( data ) ;
23+
24+ const res = Atomics . wait ( metaView , TO_WORKER , 0 , timeout ) ;
25+ Atomics . store ( metaView , TO_WORKER , 0 ) ;
26+
27+ if ( res === 'ok' ) {
28+ const obj = read ( data , OFFSET ) ;
29+
30+ const api = { } ;
31+ for ( const key of obj ) {
32+ api [ key ] = ( ...args ) => {
33+ write ( data , { key, args } , OFFSET ) ;
34+ Atomics . store ( metaView , TO_MAIN , 1 ) ;
35+ Atomics . notify ( metaView , TO_MAIN , 1 ) ;
36+ const res = Atomics . wait ( metaView , TO_WORKER , 0 , timeout ) ;
37+ Atomics . store ( metaView , TO_WORKER , 0 ) ;
38+ if ( res === 'ok' ) {
39+ const obj = read ( data , OFFSET ) ;
40+ return obj ;
41+ } else {
42+ throw new Error ( `The response timed out after ${ timeout } ms` ) ;
43+ }
44+ } ;
45+ }
46+
47+ return api ;
48+ } else {
49+ throw new Error ( `The initialization timed out after ${ timeout } ms` ) ;
50+ }
51+ }
52+
53+ /**
54+ * Wires up a shared memory buffer to invoke methods on an object.
55+ * This function is meant to be used in a worker thread to expose methods
56+ * to the main thread that has called `makeSync()` on the same shared memory.
57+ *
58+ * @param {SharedArrayBuffer } data - The shared memory buffer for communication
59+ * @param {Object } obj - Object with methods to expose to the main thread
60+ * @returns {Promise<void> } - A promise that never resolves unless there's an error
61+ */
62+ async function wire ( data , obj ) {
63+ write ( data , Object . keys ( obj ) , OFFSET ) ;
64+
65+ const metaView = new Int32Array ( data ) ;
66+
67+ Atomics . store ( metaView , TO_WORKER , 1 ) ;
68+ Atomics . notify ( metaView , TO_WORKER ) ;
69+
70+ while ( true ) {
71+ const waitAsync = Atomics . waitAsync ( metaView , TO_MAIN , 0 ) ;
72+ const res = await waitAsync . value ;
73+ Atomics . store ( metaView , TO_MAIN , 0 ) ;
74+
75+ if ( res === 'ok' ) {
76+ const { key, args } = read ( data , OFFSET ) ;
77+ // This is where the magic happens - invoke the requested method
78+ const result = await obj [ key ] ( ...args ) ;
79+ write ( data , result , OFFSET ) ;
80+ Atomics . store ( metaView , TO_WORKER , 1 ) ;
81+ Atomics . notify ( metaView , TO_WORKER , 1 ) ;
82+ }
83+ }
84+ }
85+
86+ module . exports = {
87+ makeSync,
88+ wire
89+ } ;
0 commit comments