Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cppwinrt/code_writers.h
Original file line number Diff line number Diff line change
Expand Up @@ -1433,24 +1433,28 @@ namespace cppwinrt
else if (type_name == "Windows.Foundation.IAsyncAction")
{
w.write(R"( auto get() const;
auto get_only_safe_from_non_presenting_sta() const;
auto wait_for(Windows::Foundation::TimeSpan const& timeout) const;
)");
}
else if (type_name == "Windows.Foundation.IAsyncOperation`1")
{
w.write(R"( auto get() const;
auto get_only_safe_from_non_presenting_sta() const;
auto wait_for(Windows::Foundation::TimeSpan const& timeout) const;
)");
}
else if (type_name == "Windows.Foundation.IAsyncActionWithProgress`1")
{
w.write(R"( auto get() const;
auto get_only_safe_from_non_presenting_sta() const;
auto wait_for(Windows::Foundation::TimeSpan const& timeout) const;
)");
}
else if (type_name == "Windows.Foundation.IAsyncOperationWithProgress`2")
{
w.write(R"( auto get() const;
auto get_only_safe_from_non_presenting_sta() const;
auto wait_for(Windows::Foundation::TimeSpan const& timeout) const;
)");
}
Expand Down
33 changes: 33 additions & 0 deletions strings/base_coroutine_foundation.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,19 @@ namespace winrt::impl
return async.GetResults();
}

template <typename Async>
auto wait_get_bypass_sta_check(Async const& async)
{
auto status = async.Status();
if (status == Windows::Foundation::AsyncStatus::Started)
{
status = wait_for_completed(async, 0xFFFFFFFF); // INFINITE
}
check_status_canceled(status);

return async.GetResults();
}

#ifdef WINRT_IMPL_COROUTINES
struct ignore_apartment_context {};

Expand Down Expand Up @@ -220,6 +233,11 @@ namespace winrt::impl
impl::wait_get(static_cast<Windows::Foundation::IAsyncAction const&>(static_cast<D const&>(*this)));
}
template <typename D>
auto consume_Windows_Foundation_IAsyncAction<D>::get_only_safe_from_non_presenting_sta() const
{
impl::wait_get_bypass_sta_check(static_cast<Windows::Foundation::IAsyncAction const&>(static_cast<D const&>(*this)));
}
template <typename D>
auto consume_Windows_Foundation_IAsyncAction<D>::wait_for(Windows::Foundation::TimeSpan const& timeout) const
{
return impl::wait_for(static_cast<Windows::Foundation::IAsyncAction const&>(static_cast<D const&>(*this)), timeout);
Expand All @@ -231,6 +249,11 @@ namespace winrt::impl
return impl::wait_get(static_cast<Windows::Foundation::IAsyncOperation<TResult> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TResult>
auto consume_Windows_Foundation_IAsyncOperation<D, TResult>::get_only_safe_from_non_presenting_sta() const
{
return impl::wait_get_bypass_sta_check(static_cast<Windows::Foundation::IAsyncOperation<TResult> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TResult>
auto consume_Windows_Foundation_IAsyncOperation<D, TResult>::wait_for(Windows::Foundation::TimeSpan const& timeout) const
{
return impl::wait_for(static_cast<Windows::Foundation::IAsyncOperation<TResult> const&>(static_cast<D const&>(*this)), timeout);
Expand All @@ -242,6 +265,11 @@ namespace winrt::impl
impl::wait_get(static_cast<Windows::Foundation::IAsyncActionWithProgress<TProgress> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TProgress>
auto consume_Windows_Foundation_IAsyncActionWithProgress<D, TProgress>::get_only_safe_from_non_presenting_sta() const
{
impl::wait_get_bypass_sta_check(static_cast<Windows::Foundation::IAsyncActionWithProgress<TProgress> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TProgress>
auto consume_Windows_Foundation_IAsyncActionWithProgress<D, TProgress>::wait_for(Windows::Foundation::TimeSpan const& timeout) const
{
return impl::wait_for(static_cast<Windows::Foundation::IAsyncActionWithProgress<TProgress> const&>(static_cast<D const&>(*this)), timeout);
Expand All @@ -253,6 +281,11 @@ namespace winrt::impl
return impl::wait_get(static_cast<Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TResult, typename TProgress>
auto consume_Windows_Foundation_IAsyncOperationWithProgress<D, TResult, TProgress>::get_only_safe_from_non_presenting_sta() const
{
return impl::wait_get_bypass_sta_check(static_cast<Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress> const&>(static_cast<D const&>(*this)));
}
template <typename D, typename TResult, typename TProgress>
auto consume_Windows_Foundation_IAsyncOperationWithProgress<D, TResult, TProgress>::wait_for(Windows::Foundation::TimeSpan const& timeout) const
{
return impl::wait_for(static_cast<Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress> const&>(static_cast<D const&>(*this)), timeout);
Expand Down
33 changes: 33 additions & 0 deletions test/test_nocoro/get.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;

template<typename TResult>
struct async_completion_source : implements<async_completion_source<TResult>, IAsyncOperation<TResult>, IAsyncInfo>
Expand Down Expand Up @@ -72,3 +73,35 @@ TEST_CASE("get")

REQUIRE(acs.as<IAsyncOperation<uint32_t>>().get() == 0xDEADBEEF);
}

TEST_CASE("get_only_safe_from_non_presenting_sta")
{
// Call a real WinRT async operation from an STA thread.
// This is the scenario the new API is designed for: an STA that is not
// presenting UI, where a synchronous blocking wait is safe.
std::exception_ptr failure{};
std::thread sta_thread([&failure]
{
try
{
winrt::init_apartment(winrt::apartment_type::single_threaded);

auto content = PathIO::ReadTextAsync(L"C:\\Windows\\win.ini").get_only_safe_from_non_presenting_sta();

REQUIRE(content.size() > 0);

winrt::uninit_apartment();
}
catch (...)
{
failure = std::current_exception();
}
});

sta_thread.join();

if (failure)
{
std::rethrow_exception(failure);
}
}
1 change: 1 addition & 0 deletions test/test_nocoro/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

#include "catch.hpp"
#include "winrt/Windows.Foundation.h"
#include "winrt/Windows.Storage.h"

using namespace std::literals;