KEMBAR78
Update `windows-future` with `join` and `when` functions by kennykerr · Pull Request #3708 · microsoft/windows-rs · GitHub
Skip to content

Conversation

kennykerr
Copy link
Collaborator

I originally implemented support for the Windows IAsyncXxx interfaces in the windows-future crate to match how I had implemented it for C++/WinRT and while the async pattern must be implemented in exactly the same way to interop reliably, the language-specific helpers need not look exactly the same. The C++ version included a blocking get method to wait for the results. This was based on C++'s std::future but I realized that this is not very intuitive for Rust developers who might equate this more naturally with Rust's JoinHandle. I might create a thread and wait for its result using the Standard Library as follows:

let thread = std::thread::spawn(|| 123);

let result = thread.join().unwrap();
println!("{result}");

This update renames the existing get method to join so that it follows the same pattern:

let future = windows_future::IAsyncOperation::spawn(|| Ok(123));

let result = future.join().unwrap();
println!("{result}");

The join method works exactly the same and is implemented in the same way as before, although the implementation is now more streamlined to simplify maintenance.

This update also adds the when method. While the windows-future crate implements the Standard Library's IntoFuture and Future traits, this isn't for everyone and you might just want a simple way to execute a closure when the future completes but without blocking the calling thread as join does. Wiring this up is syntactically complicated for historical reasons:

let future = windows_future::IAsyncOperation::spawn(|| Ok(123));

future
    .SetCompleted(&windows_future::AsyncOperationCompletedHandler::new(
        |sender, _| {
            let result = sender.unwrap().GetResults().unwrap();
            println!("{result:?}");
            Ok(())
        },
    ))
    .unwrap();

That's what when is for. It greatly simplifies this scenario:

let future = windows_future::IAsyncOperation::spawn(|| Ok(123));

future.when(|result| println!("{result:?}")).unwrap();

@kennykerr
Copy link
Collaborator Author

Comments on the name when? Options:

  • when
  • then
  • chain
  • something else

@kennykerr kennykerr requested a review from ChrisDenton August 12, 2025 16:14
@Permik
Copy link

Permik commented Aug 13, 2025

I'd just call it .await_then
The waiting is happening asynchronously and then the closure is called

The reasoning feels self evident, but nonetheless:

v--------- Asynchronous
A-wait <-- Wait

then is used basically everywhere in std to mean a lazily executed block.

@kennykerr
Copy link
Collaborator Author

Naming is hard! 🙃

I'm not sure I want to use the word "await" due to its association with Rust futures and I'd rather have something simple like when or then. While then is common in Rust, it typically means something that happens under a certain condition but that's not the case here. So I may just stick with "when" as I can't find a direct parallel in the Rust Standard Library that won't potentially mislead the casual reader.

@kennykerr kennykerr merged commit 2030b20 into master Aug 14, 2025
29 checks passed
@kennykerr kennykerr deleted the future-when-join branch August 14, 2025 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants