@@ -389,7 +389,7 @@ int emscripten_proxy_sync_with_ctx(em_proxying_queue* q,
389
389
}
390
390
391
391
// Helper for signaling the end of the task after the user function returns.
392
- static void call_then_finish_sync (em_proxying_ctx * ctx , void * arg ) {
392
+ static void call_then_finish_task (em_proxying_ctx * ctx , void * arg ) {
393
393
task * t = arg ;
394
394
t -> func (t -> arg );
395
395
emscripten_proxy_finish (ctx );
@@ -401,7 +401,7 @@ int emscripten_proxy_sync(em_proxying_queue* q,
401
401
void * arg ) {
402
402
task t = {.func = func , .arg = arg };
403
403
return emscripten_proxy_sync_with_ctx (
404
- q , target_thread , call_then_finish_sync , & t );
404
+ q , target_thread , call_then_finish_task , & t );
405
405
}
406
406
407
407
static int do_proxy_callback (em_proxying_queue * q ,
@@ -465,7 +465,8 @@ int emscripten_proxy_callback(em_proxying_queue* q,
465
465
void (* callback )(void * ),
466
466
void (* cancel )(void * ),
467
467
void * arg ) {
468
- // Allocate the em_proxying_ctx and the user ctx as a single block.
468
+ // Allocate the em_proxying_ctx and the user ctx as a single block that will
469
+ // be freed when the `em_proxying_ctx` is freed.
469
470
struct block {
470
471
em_proxying_ctx ctx ;
471
472
callback_ctx cb_ctx ;
@@ -483,3 +484,99 @@ int emscripten_proxy_callback(em_proxying_queue* q,
483
484
& block -> cb_ctx ,
484
485
& block -> ctx );
485
486
}
487
+
488
+ typedef struct promise_ctx {
489
+ void (* func )(em_proxying_ctx * , void * );
490
+ void * arg ;
491
+ em_promise_t promise ;
492
+ } promise_ctx ;
493
+
494
+ static void promise_call (em_proxying_ctx * ctx , void * arg ) {
495
+ promise_ctx * promise_ctx = arg ;
496
+ promise_ctx -> func (ctx , promise_ctx -> arg );
497
+ }
498
+
499
+ static void promise_fulfill (void * arg ) {
500
+ promise_ctx * promise_ctx = arg ;
501
+ emscripten_promise_resolve (promise_ctx -> promise , EM_PROMISE_FULFILL , NULL );
502
+ emscripten_promise_destroy (promise_ctx -> promise );
503
+ }
504
+
505
+ static void promise_reject (void * arg ) {
506
+ promise_ctx * promise_ctx = arg ;
507
+ emscripten_promise_resolve (promise_ctx -> promise , EM_PROMISE_REJECT , NULL );
508
+ emscripten_promise_destroy (promise_ctx -> promise );
509
+ }
510
+
511
+ static em_promise_t do_proxy_promise (em_proxying_queue * q ,
512
+ pthread_t target_thread ,
513
+ void (* func )(em_proxying_ctx * , void * ),
514
+ void * arg ,
515
+ em_promise_t promise ,
516
+ em_proxying_ctx * ctx ,
517
+ promise_ctx * promise_ctx ) {
518
+ * promise_ctx = (struct promise_ctx ){func , arg , promise };
519
+ if (!do_proxy_callback (q ,
520
+ target_thread ,
521
+ promise_call ,
522
+ promise_fulfill ,
523
+ promise_reject ,
524
+ promise_ctx ,
525
+ ctx )) {
526
+ emscripten_promise_resolve (promise , EM_PROMISE_REJECT , NULL );
527
+ return promise ;
528
+ }
529
+ // Return a separate promise to ensure that the internal promise will stay
530
+ // alive until the callbacks are called.
531
+ em_promise_t ret = emscripten_promise_create ();
532
+ emscripten_promise_resolve (ret , EM_PROMISE_MATCH , promise );
533
+ return ret ;
534
+ }
535
+
536
+ em_promise_t emscripten_proxy_promise_with_ctx (em_proxying_queue * q ,
537
+ pthread_t target_thread ,
538
+ void (* func )(em_proxying_ctx * ,
539
+ void * ),
540
+ void * arg ) {
541
+ em_promise_t promise = emscripten_promise_create ();
542
+ // Allocate the em_proxying_ctx and promise ctx as a single block that will be
543
+ // freed when the `em_proxying_ctx` is freed.
544
+ struct block {
545
+ em_proxying_ctx ctx ;
546
+ promise_ctx promise_ctx ;
547
+ };
548
+ struct block * block = malloc (sizeof (* block ));
549
+ if (block == NULL ) {
550
+ emscripten_promise_resolve (promise , EM_PROMISE_REJECT , NULL );
551
+ return promise ;
552
+ }
553
+ return do_proxy_promise (
554
+ q , target_thread , func , arg , promise , & block -> ctx , & block -> promise_ctx );
555
+ }
556
+
557
+ em_promise_t emscripten_proxy_promise (em_proxying_queue * q ,
558
+ pthread_t target_thread ,
559
+ void (* func )(void * ),
560
+ void * arg ) {
561
+ em_promise_t promise = emscripten_promise_create ();
562
+ // Allocate the em_proxying_ctx, promise ctx, and user task as a single block
563
+ // that will be freed when the `em_proxying_ctx` is freed.
564
+ struct block {
565
+ em_proxying_ctx ctx ;
566
+ promise_ctx promise_ctx ;
567
+ task task ;
568
+ };
569
+ struct block * block = malloc (sizeof (* block ));
570
+ if (block == NULL ) {
571
+ emscripten_promise_resolve (promise , EM_PROMISE_REJECT , NULL );
572
+ return promise ;
573
+ }
574
+ block -> task = (task ){.func = func , .arg = arg };
575
+ return do_proxy_promise (q ,
576
+ target_thread ,
577
+ call_then_finish_task ,
578
+ & block -> task ,
579
+ promise ,
580
+ & block -> ctx ,
581
+ & block -> promise_ctx );
582
+ }
0 commit comments