Skip to content

Add get_only_safe_from_non_presenting_sta() to async operations#1565

Open
ChrisGuzak wants to merge 1 commit intomasterfrom
user/chrisg/get-only-safe-from-non-presenting-sta
Open

Add get_only_safe_from_non_presenting_sta() to async operations#1565
ChrisGuzak wants to merge 1 commit intomasterfrom
user/chrisg/get-only-safe-from-non-presenting-sta

Conversation

@ChrisGuzak
Copy link
Copy Markdown
Member

Summary

Add a peer to .get() on all four WinRT async interfaces (IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress) that skips the _DEBUG-only STA blocking assert.

Motivation

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 _DEBUG-only (WINRT_ASSERT is a no-op in release), making it invisible to codebases that don't build with _DEBUG (e.g. the Windows OS). This means the protection is already weak.

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() definitions for all 4 async consume templates
  • cppwinrt/code_writers.h: Add declaration to code-generated output for all 4 async types
  • test/test_nocoro: Add test that calls the new method from an STA thread using a real WinRT async operation (PathIO::ReadTextAsync on C:\Windows\win.ini)

Testing

Full solution builds clean. test_nocoro passes (2 assertions in 2 test cases), including the new STA-based test.

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>
@jonwis
Copy link
Copy Markdown
Member

jonwis commented Apr 17, 2026

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

sylveon commented Apr 17, 2026

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
Copy link
Copy Markdown
Contributor

YexuanXiao commented Apr 17, 2026

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.

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