@@ -1069,6 +1069,90 @@ var LibraryPThread = {
10691069#endif
10701070 } ,
10711071
1072+ #if MAIN_MODULE
1073+ $promiseMap : "new Map ( ) ; ",
1074+ $nextPromiseId : 1 ,
1075+
1076+ // Create a new promise that can be resolved or rejected by passing
1077+ // a unique ID to emscripten_promise_resolve/emscripten_promise_reject
1078+ // TODO(sbc): Should be factor this out and make this API public?
1079+ $newNativePromise__deps : [ '$promiseMap' , '$nextPromiseId' ] ,
1080+ $newNativePromise : function ( func , args ) {
1081+ return new Promise ( ( resolve , reject ) => {
1082+ var promiseId = nextPromiseId ;
1083+ nextPromiseId += 1 ;
1084+ #if RUNTIME_DEBUG
1085+ dbg ( 'newNativePromise: ' + promiseId ) ;
1086+ #endif
1087+ promiseMap . set ( promiseId , { resolve, reject} ) ;
1088+ // Native promise function take promise ID as last argument
1089+ args . push ( promiseId ) ;
1090+ func . apply ( null , args ) ;
1091+ } ) ;
1092+ } ,
1093+
1094+ _emscripten_promise_resolve__deps : [ '$promiseMap' ] ,
1095+ _emscripten_promise_resolve__sig : 'vip' ,
1096+ _emscripten_promise_resolve : function ( id , value ) {
1097+ #if RUNTIME_DEBUG
1098+ err ( 'emscripten_resolve_promise: ' + id ) ;
1099+ #endif
1100+ assert ( promiseMap . has ( id ) ) ;
1101+ promiseMap . get ( id ) . resolve ( value ) ;
1102+ promiseMap . delete ( id ) ;
1103+ } ,
1104+
1105+ _emscripten_promise_reject__deps : [ '$promiseMap' ] ,
1106+ _emscripten_promise_reject__sig : 'vip' ,
1107+ _emscripten_promise_reject : function ( id ) {
1108+ #if RUNTIME_DEBUG
1109+ dbg ( 'emscripten_promise_reject: ' + id ) ;
1110+ #endif
1111+ assert ( promiseMap . has ( id ) ) ;
1112+ promiseMap . get ( id ) . reject ( ) ;
1113+ } ,
1114+
1115+ // Called on the main thread to syncronize the code loaded on all threads.
1116+ // This work happens asyncronously. The `callback` is called once this work
1117+ // is completely, passing the ctx.
1118+ // TODO(sbc): Should make a new form of __proxy attribute for JS library
1119+ // function that run asyncroubly like but block the caller until they are
1120+ // done. Perhaps "async_with_ctx"?
1121+ _emscripten_sync_all_threads__sig : 'viii' ,
1122+ _emscripten_sync_all_threads__deps : [ '_emscripten_proxy_sync_code' , '$newNativePromise' ] ,
1123+ _emscripten_sync_all_threads : function ( caller , callback , ctx ) {
1124+ #if PTHREADS_DEBUG
1125+ dbg ( "_emscripten_sync_all_threads caller=" + ptrToString ( caller ) ) ;
1126+ #endif
1127+ #if ASSERTIONS
1128+ assert ( ! ENVIRONMENT_IS_PTHREAD , 'Internal Error! _emscripten_sync_all_threads() can only ever be called from main thread' ) ;
1129+ #endif
1130+
1131+ let promises = [ ] ;
1132+
1133+ // This first promise resolves once the main thread has loaded all module
1134+ promises . push ( newNativePromise ( __emscripten_thread_sync_code_async , [ ] ) ) ;
1135+
1136+ // We then create a sequence of promises, one per thread, that resolve once
1137+ // each thread has performed its sync using _emscripten_proxy_sync_code.
1138+ for ( const ptr of Object . keys ( PThread . pthreads ) ) {
1139+ const pthread_ptr = Number ( ptr ) ;
1140+ if ( pthread_ptr !== caller ) {
1141+ promises . push ( newNativePromise ( __emscripten_proxy_sync_code , [ pthread_ptr ] ) ) ;
1142+ }
1143+ }
1144+
1145+ // Once all promises are resolved then we we know all threads are in
1146+ // sync and we can call the callback.
1147+ Promise . all ( promises ) . then ( ( ) => {
1148+ #if PTHREADS_DEBUG
1149+ dbg ( "_emscripten_sync_all_threads done: calling callback" ) ;
1150+ #endif
1151+ { { { makeDynCall ( 'vp' , 'callback' ) } } } ( ctx ) ;
1152+ } ) ;
1153+ } ,
1154+ #endif
1155+
10721156 $executeNotifiedProxyingQueue : function ( queue ) {
10731157 // Set the notification state to processing.
10741158 Atomics . store ( HEAP32 , queue >> 2 , { { { cDefine ( 'NOTIFICATION_RECEIVED' ) } } } ) ;
0 commit comments