22
33const os = require ( 'os' )
44const { Worker } = require ( 'worker_threads' )
5+ const { parseCamaroJson } = require ( './json-parse' )
56const {
67 sabEnabled,
78 createSabChannel,
@@ -10,6 +11,7 @@ const {
1011 readResultFromSab,
1112 stripXmlFromTask,
1213 CTRL ,
14+ STATE ,
1315 fnCode,
1416} = require ( './sab-ipc' )
1517
@@ -42,6 +44,10 @@ class LeanWorker {
4244 this . idleTimeout = idleTimeout
4345 this . onRecycleXml = onRecycleXml
4446 this . useSab = useSab
47+ this . useSabWait =
48+ useSab &&
49+ typeof Atomics . waitAsync === 'function' &&
50+ typeof Atomics . notify === 'function'
4551 this . sabChannel = useSab ? createSabChannel ( ) : null
4652 this . worker = null
4753 this . seq = 0
@@ -59,7 +65,7 @@ class LeanWorker {
5965 this . sabChannel != null ? { workerData : { sab : this . sabChannel } } : undefined
6066 const worker = new Worker ( this . filename , workerOpts )
6167 worker . unref ( )
62- worker . on ( 'message' , ( { id, result, error, xmlBuf, sab } ) => {
68+ worker . on ( 'message' , ( { id, result, error, xmlBuf, sab, raw } ) => {
6369 if ( xmlBuf && this . onRecycleXml ) this . onRecycleXml ( xmlBuf )
6470 const p = this . pending . get ( id )
6571 this . pending . delete ( id )
@@ -72,6 +78,12 @@ class LeanWorker {
7278 } catch ( err ) {
7379 p . reject ( err )
7480 }
81+ } else if ( raw ) {
82+ try {
83+ p . resolve ( parseCamaroJson ( result ) )
84+ } catch ( err ) {
85+ p . reject ( err )
86+ }
7587 } else {
7688 p . resolve ( result )
7789 }
@@ -105,6 +117,35 @@ class LeanWorker {
105117 this . idleTimer . unref ( )
106118 }
107119
120+ settleSabResult ( id ) {
121+ if (
122+ ! this . sabChannel ||
123+ Atomics . load ( this . sabChannel . control , CTRL . STATE ) !== STATE . DONE
124+ ) {
125+ return
126+ }
127+ const p = this . pending . get ( id )
128+ this . pending . delete ( id )
129+ if ( ! p ) return
130+ try {
131+ p . resolve ( readResultFromSab ( this . sabChannel ) )
132+ } catch ( err ) {
133+ p . reject ( err )
134+ }
135+ if ( this . pending . size === 0 ) this . scheduleIdleShutdown ( )
136+ }
137+
138+ waitForSabResult ( id ) {
139+ const channel = this . sabChannel
140+ if ( ! channel ) return
141+ const waiter = Atomics . waitAsync ( channel . control , CTRL . STATE , STATE . BUSY )
142+ if ( waiter . async ) {
143+ waiter . value . then ( ( ) => this . settleSabResult ( id ) )
144+ } else {
145+ this . settleSabResult ( id )
146+ }
147+ }
148+
108149 run ( task , opts = { } ) {
109150 this . ensureWorker ( )
110151 this . clearIdleTimer ( )
@@ -124,11 +165,16 @@ class LeanWorker {
124165 }
125166 return new Promise ( ( resolve , reject ) => {
126167 this . pending . set ( id , { resolve, reject } )
168+ if ( this . useSabWait ) {
169+ Atomics . store ( this . sabChannel . control , CTRL . STATE , STATE . BUSY )
170+ }
127171 this . worker . postMessage ( {
128172 id,
129173 sab : true ,
174+ waitForSab : this . useSabWait ,
130175 task : stripXmlFromTask ( task ) ,
131176 } )
177+ if ( this . useSabWait ) this . waitForSabResult ( id )
132178 } )
133179 }
134180
0 commit comments