Skip to content

Add get_unchecked() to async operations - #1565

Merged
Chris Guzak (ChrisGuzak) merged 3 commits into
masterfrom
user/chrisg/get-only-safe-from-non-presenting-sta
Aug 26, 2026
Merged

Add get_unchecked() to async operations#1565
Chris Guzak (ChrisGuzak) merged 3 commits into
masterfrom
user/chrisg/get-only-safe-from-non-presenting-sta

Conversation

@ChrisGuzak

@ChrisGuzak Chris Guzak (ChrisGuzak) commented Apr 12, 2026

Copy link
Copy Markdown
Member

Summary

Add get_unchecked() as a peer to .get() on all four WinRT async interfaces (IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress). It synchronously waits for the operation and returns the same result as .get(), but deliberately skips the STA blocking assertion.

Motivation

The existing .get() asserts !is_sta_thread() to guard against blocking a UI thread. However:

  • Not all STAs are UI threads — some never present UI, have not presented UI yet, or never will.
  • The assert is _DEBUG-onlyWINRT_ASSERT is a no-op in release builds, making this protection invisible to codebases that do not build with _DEBUG (for example, the Windows OS).

get_unchecked() has the same synchronous wait and result/error behavior as .get(). Its only behavioral difference is that it does not call the STA check before waiting. Because blocking an STA that owns or presents UI can deadlock, callers must use this method only when they know the STA is non-presenting and the wait is safe.

Changes

  • strings/base_coroutine_foundation.h: Add the wait_get_bypass_sta_check() implementation helper and get_unchecked() definitions for all four async consume templates
  • cppwinrt/code_writers.h: Add the get_unchecked() declaration to generated output for all four async types, with a comment documenting the safety contract
  • test/test_nocoro: Add a test that calls get_unchecked() from an STA thread using a real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini)

Testing

The existing STA-specific test exercises the new API on a non-presenting STA and verifies that the asynchronous operation completes successfully. A local test_nocoro build with the newest MSVC toolset is currently blocked by the toolchain's hard error for the deprecated <experimental/coroutine> header; the repository's C++17 /await:strict configuration needs a separate compatibility fix.

@jonwis

Copy link
Copy Markdown
Member

Not the hugest fan of the very_long_function_name but I don't have a better answer quite yet. Things that come to mind:

  • get_unchecked
  • get_always
  • get_any_thread
  • get_allowed_on_non_ui
  • get_blocking (although "get" is already implied blocking, this is just a place to hang the new behavior)

@sylveon

Copy link
Copy Markdown
Contributor

I think get_unchecked() is probably the best one, it immediately flags to the reader this requires extra carefulness while not being overly verbose.

@YexuanXiao

Yexuan Xiao (YexuanXiao) commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

How about naming it get_on_sta and using the reverse assertion is_sta_thread()? This can prevent the apartment from being accidentally modified. I think it helps to see the intention at a glance at any time.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a new synchronous “get-like” API across the four WinRT async interfaces that intentionally bypasses the _DEBUG-only STA blocking assert, enabling blocking waits from STAs that are not presenting UI.

Changes:

  • Added get_only_safe_from_non_presenting_sta() to the consume extensions for IAsyncAction, IAsyncOperation<T>, IAsyncActionWithProgress<T>, and IAsyncOperationWithProgress<T, P>.
  • Added an internal helper impl::wait_get_bypass_sta_check() mirroring the existing .get() wait/get behavior but skipping the STA assert.
  • Added a test_nocoro test that invokes the new method from an STA thread using Windows::Storage::PathIO::ReadTextAsync.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
test/test_nocoro/pch.h Adds Windows.Storage include to support the new test’s WinRT API usage.
test/test_nocoro/get.cpp Adds an STA-threaded test case exercising get_only_safe_from_non_presenting_sta().
strings/base_coroutine_foundation.h Implements the bypass helper and wires the new method into async consume templates.
cppwinrt/code_writers.h Updates generated interface extension declarations to include the new method.

Comment thread test/test_nocoro/get.cpp Outdated
Comment thread test/test_nocoro/get.cpp Outdated
Chris Guzak (WINDOWS) and others added 2 commits August 25, 2026 22:15
Add a peer to .get() on IAsyncAction, IAsyncOperation, IAsyncActionWithProgress,
and IAsyncOperationWithProgress that skips the _DEBUG-only STA blocking assert.

The existing .get() asserts !is_sta_thread() to guard against blocking UI threads.
However, not all STAs are UI threads — some never present UI, haven't presented yet,
or never will. The assert is also _DEBUG-only, making it invisible to codebases that
don't build with _DEBUG (e.g. the Windows OS).

The new method get_only_safe_from_non_presenting_sta() is functionally identical to
.get() but omits the STA check. The intentionally long name communicates the risk
to callers.

Changes:
- strings/base_coroutine_foundation.h: Add wait_get_bypass_sta_check() impl helper
  and get_only_safe_from_non_presenting_sta() for all 4 async consume templates
- cppwinrt/code_writers.h: Add declaration to generated code for all 4 async types
- test/test_nocoro: Add test calling the new method from an STA thread using a
  real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ChrisGuzak Chris Guzak (ChrisGuzak) changed the title Add get_only_safe_from_non_presenting_sta() to async operations Add get_unchecked() to async operations Aug 26, 2026
@jonwis

Copy link
Copy Markdown
Member

Seems good; the description says get_unchecked() while your implementation has the more readable version. Maybe update the description?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

wait, I think Jon's observation cuts the other way. the code has the weird long name, the description has the agreed-upon short name?

@sylveon

Copy link
Copy Markdown
Contributor

Yeah, the title and description was just recently updated. I suppose a commit to use the new name is upcoming?

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@ChrisGuzak
Chris Guzak (ChrisGuzak) merged commit 9cf9564 into master Aug 26, 2026
89 checks passed
@ChrisGuzak
Chris Guzak (ChrisGuzak) deleted the user/chrisg/get-only-safe-from-non-presenting-sta branch August 26, 2026 23:14
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.

6 participants