@@ -431,21 +431,76 @@ pub fn block_on<T: 'static>(future: impl Future<Output = T> + 'static) -> T {
431
431
/// Call the `yield` canonical built-in function.
432
432
///
433
433
/// This yields control to the host temporarily, allowing other tasks to make
434
- /// progress. It's a good idea to call this inside a busy loop which does not
435
- /// otherwise ever yield control the the host.
436
- pub fn task_yield ( ) {
434
+ /// progress. It's a good idea to call this inside a busy loop which does not
435
+ /// otherwise ever yield control the host.
436
+ ///
437
+ /// Note that this function is a blocking function, not an `async` function.
438
+ /// That means that this is not an async yield which allows other tasks in this
439
+ /// component to progress, but instead this will block the current function
440
+ /// until the host gets back around to returning from this yield. Asynchronous
441
+ /// functions should probably use [`yield_async`] instead.
442
+ ///
443
+ /// # Return Value
444
+ ///
445
+ /// This function returns a `bool` which indicates whether execution should
446
+ /// continue after this yield point. A return value of `true` means that the
447
+ /// task was not cancelled and execution should continue. A return value of
448
+ /// `false`, however, means that the task was cancelled while it was suspended
449
+ /// at this yield point. The caller should return back and exit from the task
450
+ /// ASAP in this situation.
451
+ pub fn yield_blocking ( ) -> bool {
437
452
#[ cfg( not( target_arch = "wasm32" ) ) ]
438
- unsafe fn yield_ ( ) {
453
+ unsafe fn yield_ ( ) -> bool {
439
454
unreachable ! ( ) ;
440
455
}
441
456
442
457
#[ cfg( target_arch = "wasm32" ) ]
443
458
#[ link( wasm_import_module = "$root" ) ]
444
459
extern "C" {
445
460
#[ link_name = "[yield]" ]
446
- fn yield_ ( ) ;
461
+ fn yield_ ( ) -> bool ;
447
462
}
448
- unsafe { yield_ ( ) }
463
+ // Note that the return value from the raw intrinsic is inverted, the
464
+ // canonical ABI returns "did this task get cancelled" while this function
465
+ // works as "should work continue going".
466
+ unsafe { !yield_ ( ) }
467
+ }
468
+
469
+ /// The asynchronous counterpart to [`yield_blocking`].
470
+ ///
471
+ /// This function does not block the current task but instead gives the
472
+ /// Rust-level executor a chance to yield control back to the host temporarily.
473
+ /// This means that other Rust-level tasks may also be able to progress during
474
+ /// this yield operation.
475
+ ///
476
+ /// # Return Value
477
+ ///
478
+ /// Unlike [`yield_blocking`] this function does not return anything. If this
479
+ /// component task is cancelled while paused at this yield point then the future
480
+ /// will be dropped and a Rust-level destructor will take over and clean up the
481
+ /// task. It's not necessary to do anything with the return value of this
482
+ /// function other than ensuring that you `.await` the function call.
483
+ pub async fn yield_async ( ) {
484
+ #[ derive( Default ) ]
485
+ struct Yield {
486
+ yielded : bool ,
487
+ }
488
+
489
+ impl Future for Yield {
490
+ type Output = ( ) ;
491
+
492
+ fn poll ( mut self : Pin < & mut Self > , context : & mut Context < ' _ > ) -> Poll < ( ) > {
493
+ if self . yielded {
494
+ Poll :: Ready ( ( ) )
495
+ } else {
496
+ self . yielded = true ;
497
+ context. waker ( ) . wake_by_ref ( ) ;
498
+ Poll :: Pending
499
+ }
500
+ }
501
+ }
502
+
503
+ Yield :: default ( ) . await ;
449
504
}
450
505
451
506
/// Call the `backpressure.set` canonical built-in function.
0 commit comments