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