@@ -431,21 +431,76 @@ pub fn block_on<T: 'static>(future: impl Future<Output = T> + 'static) -> T {
431431/// Call the `yield` canonical built-in function.
432432///
433433/// 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 {
437452 #[ cfg( not( target_arch = "wasm32" ) ) ]
438- unsafe fn yield_ ( ) {
453+ unsafe fn yield_ ( ) -> bool {
439454 unreachable ! ( ) ;
440455 }
441456
442457 #[ cfg( target_arch = "wasm32" ) ]
443458 #[ link( wasm_import_module = "$root" ) ]
444459 extern "C" {
445460 #[ link_name = "[yield]" ]
446- fn yield_ ( ) ;
461+ fn yield_ ( ) -> bool ;
447462 }
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 ;
449504}
450505
451506/// Call the `backpressure.set` canonical built-in function.
0 commit comments