KEMBAR78
Introduce the dedicated `windows-threading` crate by kennykerr · Pull Request #3595 · microsoft/windows-rs · GitHub
Skip to content

Conversation

@kennykerr
Copy link
Collaborator

@kennykerr kennykerr commented May 6, 2025

This update introduces the windows-threading crate as a simpler and more efficient way to handle threading on Windows. Although the Standard Library provides basic threading support, the windows-threading crate offers additional features and optimizations for Windows-specific threading tasks in a manner that is generally more efficient primarily because it leverages the Windows thread pool rather than necessarily creating new threads. This is a no_std crate that can be used with very little overhead and only depends on the windows-link crate for access to the Windows threading APIs.

The existing windows-future crate now depends on the windows-threading crate for spawning WinRT async operations. I chose to keep this functionality separate as there are cases where the added complexity and overhead of the windows-future crate may not be desirable. The windows-bindgen crate now also depends on windows-threading for speeding up package generation that was previously disabled in #3588.

The windows-threading crate is intentionally simple and easy to use but offers tremendous power to scale up tasks with good data parallelism. I may add more capabilities as need arises.

The submit function submits the closure to the default thread pool. It is similar to the Standard Library spawn function but does not require a new thread to be created. It is a very efficient way to run some work in the background and is used by the windows-future crate for implementing async operations. Waiting or joining is not currently supported but may be added in the future as a separate Work object.

The for_each function calls the closure on each element of the iterator in parallel, waiting for all closures to finish. It is a simple way to parallelize a for loop or iterator and is used by the windows-bindgen crate for speeding up package generation.

The for_each function relies on the Pool struct that represents a private thread pool with its own thread limits. Closures can be submitted to private pool objects rather than the default thread pool to manage concurrency or improve code isolation and the join method, or Drop implementation, will wait for all closures to run their course.

Here is a preview of the crate's readme with examples.

The Windows thread pool offers many other facilities but these are especially useful and broadly applicable. For more information on the Windows thread pool see my resources here:

The Windows Thread Pool and Work
The Thread Pool Environment
Thread Pool Cancellation and Cleanup
Thread Pool Synchronization
Thread Pool Timers and I/O
The Evolution of Threads and I/O in Windows
10 Practical Techniques to Power Your Visual C++ Apps

@kennykerr kennykerr requested a review from ChrisDenton May 6, 2025 19:50
Copy link
Collaborator

@ChrisDenton ChrisDenton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks fairly straight forward and is clearly written, thanks! The most tricky thing with this is handling lifetimes but using 'static or binding to Pool are safe options.

Just a couple of small nits.

kennykerr and others added 2 commits May 7, 2025 06:14
Co-authored-by: Chris Denton <chris@chrisdenton.dev>
Co-authored-by: Chris Denton <chris@chrisdenton.dev>
@kennykerr kennykerr merged commit 804aa47 into master May 7, 2025
29 checks passed
@kennykerr kennykerr deleted the threading branch May 7, 2025 13:22
@kennykerr kennykerr mentioned this pull request May 15, 2025
Comment on lines +21 to +22
pub type PTP_SIMPLE_CALLBACK = Option<
unsafe extern "system" fn(instance: PTP_CALLBACK_INSTANCE, context: *mut core::ffi::c_void),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @kennykerr, I'm once again generating new windows-rs crates against new win32metadata and noticed that upstream changed this delegate to receive zero arguments in microsoft/win32metadata@6d6617a, is that intended/correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it has two parameters as depicted here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is why I am giving you a heads-up, that this should perhaps be reported and corrected upstream. The change says (https://github.com/microsoft/win32metadata/blob/c7ffce1c97bb724580580f3856b94c6d4ad677ed/scripts/ChangesSinceLastRelease.txt#L5517-L5518):

Windows.Win32.System.Threading.PTP_SIMPLE_CALLBACK.Invoke() added
Windows.Win32.System.Threading.PTP_SIMPLE_CALLBACK.Invoke(Instance,Context) removed

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.

4 participants