diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 866fddd7d..712a8eb32 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,7 +92,7 @@ jobs: compiler: [MSVC, clang-cl] arch: [x86, x64, arm64] config: [Debug, Release] - test_exe: [test, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] + test_exe: [test, test_nocoro, test_cpp20, test_cpp20_no_sourcelocation, test_fast, test_slow, test_old, test_module_lock_custom, test_module_lock_none] exclude: - arch: arm64 config: Debug diff --git a/.pipelines/jobs/OneBranchTest.yml b/.pipelines/jobs/OneBranchTest.yml index 0aa5c934b..2fb3a4bd1 100644 --- a/.pipelines/jobs/OneBranchTest.yml +++ b/.pipelines/jobs/OneBranchTest.yml @@ -17,6 +17,10 @@ jobs: TestExe: 'test' TestProject: 'test' BuildPlatform: 'x86' + test_nocoro.x86: + TestExe: 'test_nocoro' + TestProject: 'test_nocoro' + BuildPlatform: 'x86' test_cpp20.x86: TestExe: 'test_cpp20' TestProject: 'test_cpp20' diff --git a/Directory.Build.Props b/Directory.Build.Props index 9088021c1..5f530da91 100644 --- a/Directory.Build.Props +++ b/Directory.Build.Props @@ -30,7 +30,7 @@ ClangCL - + 20 false @@ -60,7 +60,7 @@ CATCH_CONFIG_COLOUR_ANSI;%(PreprocessorDefinitions) true /bigobj - /await %(AdditionalOptions) + /await:strict %(AdditionalOptions) -Wno-unused-command-line-argument -fno-delayed-template-parsing -mcx16 diff --git a/build_test_all.cmd b/build_test_all.cmd index 4372acfd5..649f4dc69 100644 --- a/build_test_all.cmd +++ b/build_test_all.cmd @@ -28,6 +28,7 @@ call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platfor call msbuild /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% test\nuget\NugetTest.sln call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test +call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_nocoro call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20 call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_cpp20_no_sourcelocation call msbuild /m /p:Configuration=%target_configuration%,Platform=%target_platform%,CppWinRTBuildVersion=%target_version% cppwinrt.sln /t:test\test_fast diff --git a/cppwinrt.sln b/cppwinrt.sln index 5964f976b..3bcfb33bc 100644 --- a/cppwinrt.sln +++ b/cppwinrt.sln @@ -119,6 +119,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_cpp20_no_sourcelocatio {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_nocoro", "test\test_nocoro\test_nocoro.vcxproj", "{9E392830-805A-4AAF-932D-C493143EFACA}" + ProjectSection(ProjectDependencies) = postProject + {D613FB39-5035-4043-91E2-BAB323908AF4} = {D613FB39-5035-4043-91E2-BAB323908AF4} + EndProjectSection +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D15C8430-A7CD-4616-BD84-243B26A9F1C2}" ProjectSection(SolutionItems) = preProject build_nuget.cmd = build_nuget.cmd @@ -394,6 +399,18 @@ Global {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x64.Build.0 = Release|x64 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.ActiveCfg = Release|Win32 {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374}.Release|x86.Build.0 = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|ARM64.Build.0 = Debug|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.ActiveCfg = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x64.Build.0 = Debug|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.ActiveCfg = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Debug|x86.Build.0 = Debug|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.ActiveCfg = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|ARM64.Build.0 = Release|ARM64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.ActiveCfg = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x64.Build.0 = Release|x64 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.ActiveCfg = Release|Win32 + {9E392830-805A-4AAF-932D-C493143EFACA}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -417,6 +434,7 @@ Global {08C40663-B6A3-481E-8755-AE32BAD99501} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {5FF6CD6C-515A-4D55-97B6-62AD9BCB77EA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} {D4C8F881-84D5-4A7B-8BDE-AB4E34A05374} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} + {9E392830-805A-4AAF-932D-C493143EFACA} = {3C7EA5F8-6E8C-4376-B499-2CAF596384B0} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2783B8FD-EA3B-4D6B-9F81-662D289E02AA} diff --git a/cppwinrt/code_writers.h b/cppwinrt/code_writers.h index 35e9935d0..74687bad9 100644 --- a/cppwinrt/code_writers.h +++ b/cppwinrt/code_writers.h @@ -3477,10 +3477,6 @@ struct WINRT_IMPL_EMPTY_BASES produce_dispatch_to_overridable { w.write(strings::base_coroutine_system); } - else if (namespace_name == "Microsoft.System") - { - w.write(strings::base_coroutine_system_winui); - } else if (namespace_name == "Windows.UI.Core") { w.write(strings::base_coroutine_ui_core); diff --git a/nuget/CppWinrtRules.Project.xml b/nuget/CppWinrtRules.Project.xml index 7f69fcd74..73f32c6d3 100644 --- a/nuget/CppWinrtRules.Project.xml +++ b/nuget/CppWinrtRules.Project.xml @@ -81,9 +81,9 @@ Description="Enables or disables the default for copying binaries to the output folder to be false" Category="General" /> - diff --git a/nuget/Microsoft.Windows.CppWinRT.targets b/nuget/Microsoft.Windows.CppWinRT.targets index 7fe83b14d..188e56835 100644 --- a/nuget/Microsoft.Windows.CppWinRT.targets +++ b/nuget/Microsoft.Windows.CppWinRT.targets @@ -882,7 +882,7 @@ $(XamlMetaDataProviderPch) %(AdditionalOptions) /bigobj - %(AdditionalOptions) /await + %(AdditionalOptions) /await:strict %(AdditionalIncludeDirectories);$(GeneratedFilesDir) diff --git a/run_tests.cmd b/run_tests.cmd index 77d883642..58e3c5524 100644 --- a/run_tests.cmd +++ b/run_tests.cmd @@ -9,6 +9,7 @@ if "%target_platform%"=="" set target_platform=x64 if "%target_configuration%"=="" set target_configuration=Debug call :run_test test +call :run_test test_nocoro call :run_test test_cpp20 call :run_test test_cpp20_no_sourcelocation call :run_test test_fast diff --git a/strings/base_coroutine_foundation.h b/strings/base_coroutine_foundation.h index 87aaed24e..a5816a85b 100644 --- a/strings/base_coroutine_foundation.h +++ b/strings/base_coroutine_foundation.h @@ -99,12 +99,13 @@ namespace winrt::impl return async.GetResults(); } +#ifdef WINRT_IMPL_COROUTINES struct ignore_apartment_context {}; template struct disconnect_aware_handler : private std::conditional_t { - disconnect_aware_handler(Awaiter* awaiter, coroutine_handle<> handle) noexcept + disconnect_aware_handler(Awaiter* awaiter, std::coroutine_handle<> handle) noexcept : m_awaiter(awaiter), m_handle(handle) { } disconnect_aware_handler(disconnect_aware_handler&& other) = default; @@ -123,7 +124,7 @@ namespace winrt::impl private: movable_primitive m_awaiter; - movable_primitive, nullptr> m_handle; + movable_primitive, nullptr> m_handle; void Complete() { @@ -149,7 +150,6 @@ namespace winrt::impl } }; -#ifdef WINRT_IMPL_COROUTINES template struct await_adapter : cancellable_awaiter> { @@ -175,7 +175,7 @@ namespace winrt::impl } template - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle handle) { this->set_cancellable_promise_from_handle(handle); return register_completed_callback(handle); @@ -189,7 +189,7 @@ namespace winrt::impl } private: - bool register_completed_callback(coroutine_handle<> handle) + bool register_completed_callback(std::coroutine_handle<> handle) { if constexpr (!preserve_context) { @@ -294,7 +294,6 @@ WINRT_EXPORT namespace winrt::Windows::Foundation return{ async }; } } -#endif WINRT_EXPORT namespace winrt { @@ -327,7 +326,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -373,7 +372,7 @@ namespace winrt::impl return true; } - void await_suspend(coroutine_handle<>) const noexcept + void await_suspend(std::coroutine_handle<>) const noexcept { } @@ -411,7 +410,7 @@ namespace winrt::impl if (remaining == 0) { std::atomic_thread_fence(std::memory_order_acquire); - coroutine_handle::from_promise(*static_cast(this)).destroy(); + std::coroutine_handle::from_promise(*static_cast(this)).destroy(); } return remaining; @@ -577,7 +576,7 @@ namespace winrt::impl } } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } @@ -595,7 +594,7 @@ namespace winrt::impl { } - bool await_suspend(coroutine_handle<>) const noexcept + bool await_suspend(std::coroutine_handle<>) const noexcept { promise->set_completed(); uint32_t const remaining = promise->subtract_reference(); @@ -705,11 +704,7 @@ namespace winrt::impl }; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -844,7 +839,6 @@ namespace std::experimental WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template Windows::Foundation::IAsyncAction when_all(T... async) { @@ -890,5 +884,5 @@ WINRT_EXPORT namespace winrt impl::check_status_canceled(shared->status); co_return shared->result.GetResults(); } -#endif } +#endif diff --git a/strings/base_coroutine_system.h b/strings/base_coroutine_system.h index b893bd1b5..f79fe0671 100644 --- a/strings/base_coroutine_system.h +++ b/strings/base_coroutine_system.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -23,7 +24,7 @@ WINRT_EXPORT namespace winrt return m_queued; } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_dispatcher.TryEnqueue(m_priority, [handle, this] { @@ -41,10 +42,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::System::DispatcherQueue const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_coroutine_system_winui.h b/strings/base_coroutine_system_winui.h deleted file mode 100644 index ecb3cf766..000000000 --- a/strings/base_coroutine_system_winui.h +++ /dev/null @@ -1,50 +0,0 @@ - -WINRT_EXPORT namespace winrt -{ - [[nodiscard]] inline auto resume_foreground( - Microsoft::System::DispatcherQueue const& dispatcher, - Microsoft::System::DispatcherQueuePriority const priority = Microsoft::System::DispatcherQueuePriority::Normal) noexcept - { - struct awaitable - { - awaitable(Microsoft::System::DispatcherQueue const& dispatcher, Microsoft::System::DispatcherQueuePriority const priority) noexcept : - m_dispatcher(dispatcher), - m_priority(priority) - { - } - - bool await_ready() const noexcept - { - return false; - } - - bool await_resume() const noexcept - { - return m_queued; - } - - bool await_suspend(impl::coroutine_handle<> handle) - { - return m_dispatcher.TryEnqueue(m_priority, [handle, this] - { - m_queued = true; - handle(); - }); - } - - private: - Microsoft::System::DispatcherQueue const& m_dispatcher; - Microsoft::System::DispatcherQueuePriority const m_priority; - bool m_queued{}; - }; - - return awaitable{ dispatcher, priority }; - }; - -#ifdef WINRT_IMPL_COROUTINES - inline auto operator co_await(Microsoft::System::DispatcherQueue const& dispatcher) - { - return resume_foreground(dispatcher); - } -#endif -} diff --git a/strings/base_coroutine_threadpool.h b/strings/base_coroutine_threadpool.h index 7fa8789c7..e59fcadb2 100644 --- a/strings/base_coroutine_threadpool.h +++ b/strings/base_coroutine_threadpool.h @@ -1,6 +1,7 @@ namespace winrt::impl { +#ifdef WINRT_IMPL_COROUTINES inline auto submit_threadpool_callback(void(__stdcall* callback)(void*, void* context), void* context) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, context, nullptr)) @@ -11,13 +12,14 @@ namespace winrt::impl inline void __stdcall resume_background_callback(void*, void* context) noexcept { - coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); }; - inline auto resume_background(coroutine_handle<> handle) + inline auto resume_background(std::coroutine_handle<> handle) { submit_threadpool_callback(resume_background_callback, handle.address()); } +#endif inline std::pair get_apartment_type() noexcept { @@ -48,6 +50,7 @@ namespace winrt::impl return false; } +#ifdef WINRT_IMPL_COROUTINES struct resume_apartment_context { resume_apartment_context() = default; @@ -64,11 +67,11 @@ namespace winrt::impl inline int32_t __stdcall resume_apartment_callback(com_callback_args* args) noexcept { - coroutine_handle<>::from_address(args->data)(); + std::coroutine_handle<>::from_address(args->data)(); return 0; }; - [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline bool resume_apartment_sync(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { com_callback_args args{}; args.data = handle.address(); @@ -85,10 +88,10 @@ namespace winrt::impl struct threadpool_resume { - threadpool_resume(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) : + threadpool_resume(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) : m_context(context), m_handle(handle), m_failure(failure) { } com_ptr m_context; - coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; int32_t* m_failure; }; @@ -101,14 +104,14 @@ namespace winrt::impl } } - inline void resume_apartment_on_threadpool(com_ptr const& context, coroutine_handle<> handle, int32_t* failure) + inline void resume_apartment_on_threadpool(com_ptr const& context, std::coroutine_handle<> handle, int32_t* failure) { auto state = std::make_unique(context, handle, failure); submit_threadpool_callback(fallback_submit_threadpool_callback, state.get()); state.release(); } - [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, coroutine_handle<> handle, int32_t* failure) + [[nodiscard]] inline auto resume_apartment(resume_apartment_context const& context, std::coroutine_handle<> handle, int32_t* failure) { WINRT_ASSERT(context.valid()); if ((context.m_context == nullptr) || (context.m_context == try_capture(WINRT_IMPL_CoGetObjectContext))) @@ -130,8 +133,10 @@ namespace winrt::impl return resume_apartment_sync(context.m_context, handle, failure); } } +#endif } +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { struct cancellable_promise @@ -217,7 +222,7 @@ WINRT_EXPORT namespace winrt protected: template - void set_cancellable_promise_from_handle(impl::coroutine_handle const& handle) + void set_cancellable_promise_from_handle(std::coroutine_handle const& handle) { if constexpr (std::is_base_of_v) { @@ -237,10 +242,7 @@ WINRT_EXPORT namespace winrt cancellable_promise* m_promise = nullptr; }; -} -WINRT_EXPORT namespace winrt -{ [[nodiscard]] inline auto resume_background() noexcept { struct awaitable @@ -254,7 +256,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { impl::resume_background(handle); } @@ -281,7 +283,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> resume) + void await_suspend(std::coroutine_handle<> resume) { m_resume = resume; @@ -301,7 +303,7 @@ WINRT_EXPORT namespace winrt } T const& m_context; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; }; return awaitable{ context }; @@ -336,7 +338,7 @@ namespace winrt::impl check_hresult(failure); } - bool await_suspend(impl::coroutine_handle<> handle) + bool await_suspend(std::coroutine_handle<> handle) { auto context_copy = context; return impl::resume_apartment(context_copy.context, handle, &failure); @@ -381,7 +383,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle handle) + void await_suspend(std::coroutine_handle handle) { set_cancellable_promise_from_handle(handle); @@ -445,7 +447,7 @@ namespace winrt::impl handle_type m_timer; Windows::Foundation::TimeSpan m_duration; - impl::coroutine_handle<> m_handle; + std::coroutine_handle<> m_handle; std::atomic m_state{ state::idle }; }; @@ -489,7 +491,7 @@ namespace winrt::impl } template - void await_suspend(impl::coroutine_handle resume) + void await_suspend(std::coroutine_handle resume) { set_cancellable_promise_from_handle(resume); @@ -559,31 +561,27 @@ namespace winrt::impl Windows::Foundation::TimeSpan m_timeout; void* m_handle; uint32_t m_result{}; - impl::coroutine_handle<> m_resume{ nullptr }; + std::coroutine_handle<> m_resume{ nullptr }; std::atomic m_state{ state::idle }; }; } WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES inline impl::apartment_awaiter operator co_await(apartment_context const& context) { return{ context }; } -#endif [[nodiscard]] inline impl::timespan_awaiter resume_after(Windows::Foundation::TimeSpan duration) noexcept { return impl::timespan_awaiter{ duration }; } -#ifdef WINRT_IMPL_COROUTINES inline impl::timespan_awaiter operator co_await(Windows::Foundation::TimeSpan duration) { return resume_after(duration); } -#endif [[nodiscard]] inline impl::signal_awaiter resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept { @@ -613,7 +611,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) + void await_suspend(std::coroutine_handle<> handle) { if (!WINRT_IMPL_TrySubmitThreadpoolCallback(callback, handle.address(), &m_environment)) { @@ -625,7 +623,7 @@ WINRT_EXPORT namespace winrt static void __stdcall callback(void*, void* context) noexcept { - impl::coroutine_handle<>::from_address(context)(); + std::coroutine_handle<>::from_address(context)(); } struct pool_traits @@ -673,11 +671,7 @@ WINRT_EXPORT namespace winrt struct fire_and_forget {}; } -#ifdef __cpp_lib_coroutine namespace std -#else -namespace std::experimental -#endif { template struct coroutine_traits @@ -693,12 +687,12 @@ namespace std::experimental { } - suspend_never initial_suspend() const noexcept + std::suspend_never initial_suspend() const noexcept { return{}; } - suspend_never final_suspend() const noexcept + std::suspend_never final_suspend() const noexcept { return{}; } @@ -710,3 +704,4 @@ namespace std::experimental }; }; } +#endif diff --git a/strings/base_coroutine_ui_core.h b/strings/base_coroutine_ui_core.h index dab34c8de..7efed5174 100644 --- a/strings/base_coroutine_ui_core.h +++ b/strings/base_coroutine_ui_core.h @@ -1,4 +1,5 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { [[nodiscard]] inline auto resume_foreground( @@ -22,7 +23,7 @@ WINRT_EXPORT namespace winrt { } - void await_suspend(impl::coroutine_handle<> handle) const + void await_suspend(std::coroutine_handle<> handle) const { m_dispatcher.RunAsync(m_priority, [handle] { @@ -39,10 +40,9 @@ WINRT_EXPORT namespace winrt return awaitable{ dispatcher, priority }; }; -#ifdef WINRT_IMPL_COROUTINES inline auto operator co_await(Windows::UI::Core::CoreDispatcher const& dispatcher) { return resume_foreground(dispatcher); } -#endif } +#endif diff --git a/strings/base_deferral.h b/strings/base_deferral.h index ceab1cd4b..6976db4a6 100644 --- a/strings/base_deferral.h +++ b/strings/base_deferral.h @@ -1,7 +1,7 @@ +#ifdef WINRT_IMPL_COROUTINES WINRT_EXPORT namespace winrt { -#ifdef WINRT_IMPL_COROUTINES template struct deferrable_event_args { @@ -22,9 +22,9 @@ WINRT_EXPORT namespace winrt [[nodiscard]] Windows::Foundation::IAsyncAction wait_for_deferrals() { - struct awaitable : impl::suspend_always + struct awaitable : std::suspend_always { - bool await_suspend(coroutine_handle handle) + bool await_suspend(std::coroutine_handle<> handle) { return m_deferrable.await_suspend(handle); } @@ -37,11 +37,9 @@ WINRT_EXPORT namespace winrt private: - using coroutine_handle = impl::coroutine_handle<>; - void one_deferral_completed() { - coroutine_handle resume = nullptr; + std::coroutine_handle<> resume = nullptr; { slim_lock_guard const guard(m_lock); @@ -62,7 +60,7 @@ WINRT_EXPORT namespace winrt } } - bool await_suspend(coroutine_handle handle) noexcept + bool await_suspend(std::coroutine_handle<> handle) noexcept { slim_lock_guard const guard(m_lock); m_handle = handle; @@ -71,7 +69,7 @@ WINRT_EXPORT namespace winrt slim_mutex m_lock; int32_t m_outstanding_deferrals = 0; - coroutine_handle m_handle = nullptr; + std::coroutine_handle<> m_handle = nullptr; }; -#endif } +#endif diff --git a/strings/base_includes.h b/strings/base_includes.h index 819e3c98f..18a724147 100644 --- a/strings/base_includes.h +++ b/strings/base_includes.h @@ -48,31 +48,5 @@ #endif #ifdef __cpp_lib_coroutine - #include - -namespace winrt::impl -{ - template - using coroutine_handle = std::coroutine_handle; - - using suspend_always = std::suspend_always; - using suspend_never = std::suspend_never; -} - -#elif __has_include() - -#include - -namespace winrt::impl -{ - template - using coroutine_handle = std::experimental::coroutine_handle; - - using suspend_always = std::experimental::suspend_always; - using suspend_never = std::experimental::suspend_never; -} - -#else -#error C++/WinRT requires coroutine support, which is currently missing. Try enabling C++20 in your compiler. #endif diff --git a/strings/base_macros.h b/strings/base_macros.h index 0c4357b1e..3dc01fa2d 100644 --- a/strings/base_macros.h +++ b/strings/base_macros.h @@ -23,7 +23,7 @@ #pragma warning(disable : 4268) #endif -#if defined(__cpp_lib_coroutine) || defined(__cpp_coroutines) || defined(_RESUMABLE_FUNCTIONS_SUPPORTED) +#if defined(__cpp_lib_coroutine) #define WINRT_IMPL_COROUTINES #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ed1515526..e5ca6e0fb 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -105,6 +105,7 @@ set(SKIP_LARGE_PCH FALSE CACHE BOOL "Skip building large precompiled headers.") add_subdirectory(test) +add_subdirectory(test_nocoro) add_subdirectory(test_cpp20) add_subdirectory(test_cpp20_no_sourcelocation) diff --git a/test/old_tests/UnitTests/async.cpp b/test/old_tests/UnitTests/async.cpp index 037e16ab7..7a7382004 100644 --- a/test/old_tests/UnitTests/async.cpp +++ b/test/old_tests/UnitTests/async.cpp @@ -14,12 +14,6 @@ using namespace std::chrono; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - IAsyncAction NoSuspend_IAsyncAction() { co_await 0s; @@ -1118,7 +1112,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1126,7 +1120,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); } @@ -1134,7 +1128,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } @@ -1143,7 +1137,7 @@ namespace { signal_done d{ go }; co_await resume_on_signal(go); - co_await suspend_never{}; + co_await std::suspend_never{}; REQUIRE(false); co_return 0; } diff --git a/test/old_tests/UnitTests/weak.cpp b/test/old_tests/UnitTests/weak.cpp index 55c40dbe6..46b89bf6f 100644 --- a/test/old_tests/UnitTests/weak.cpp +++ b/test/old_tests/UnitTests/weak.cpp @@ -99,13 +99,13 @@ namespace // Returns an IAsyncAction that has not completed. // Call the resume() handle to complete it. - winrt::Windows::Foundation::IAsyncAction SuspendAction(impl::coroutine_handle<>& resume) + winrt::Windows::Foundation::IAsyncAction SuspendAction(std::coroutine_handle<>& resume) { struct awaiter { - impl::coroutine_handle<>& resume; + std::coroutine_handle<>& resume; bool await_ready() { return false; } - void await_suspend(impl::coroutine_handle<> handle) { resume = handle; } + void await_suspend(std::coroutine_handle<> handle) { resume = handle; } void await_resume() {} }; @@ -516,7 +516,7 @@ TEST_CASE("weak,coroutine") // Start a coroutine but don't complete it yet. // Confirm that weak references resolve. - impl::coroutine_handle<> resume; + std::coroutine_handle<> resume; weak = winrt::weak_ref(SuspendAction(resume)); REQUIRE(weak.get() != nullptr); // Now complete the coroutine. Confirm that weak references no longer resolve. diff --git a/test/test/async_auto_cancel.cpp b/test/test/async_auto_cancel.cpp index bffcb6e44..b0a541535 100644 --- a/test/test/async_auto_cancel.cpp +++ b/test/test/async_auto_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the coroutine is automatically canceled when reaching a suspension point. // @@ -18,21 +12,21 @@ namespace IAsyncAction Action(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncActionWithProgress ActionWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } IAsyncOperation Operation(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -40,7 +34,7 @@ namespace IAsyncOperationWithProgress OperationWithProgress(HANDLE event) { co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -54,7 +48,7 @@ namespace auto cancel = co_await get_cancellation_token(); cancel.callback(nullptr); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } diff --git a/test/test/async_cancel_callback.cpp b/test/test/async_cancel_callback.cpp index c99e1dad4..75a3aac0c 100644 --- a/test/test/async_cancel_callback.cpp +++ b/test/test/async_cancel_callback.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - // // Checks that the cancellation callback is invoked. // @@ -29,7 +23,7 @@ namespace }(); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -44,7 +38,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -59,7 +53,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -75,7 +69,7 @@ namespace }); co_await resume_on_signal(event); - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } diff --git a/test/test/async_check_cancel.cpp b/test/test/async_check_cancel.cpp index d88fdcaf0..c98519f06 100644 --- a/test/test/async_check_cancel.cpp +++ b/test/test/async_check_cancel.cpp @@ -5,12 +5,6 @@ using namespace Windows::Foundation; namespace { -#ifdef __cpp_lib_coroutine - using std::suspend_never; -#else - using std::experimental::suspend_never; -#endif - static bool s_exceptionLoggerCalled = false; static struct { @@ -48,7 +42,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -63,7 +57,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); } @@ -78,7 +72,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -95,7 +89,7 @@ namespace canceled = true; } - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return 1; } @@ -120,7 +114,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; @@ -147,7 +141,7 @@ namespace winrt_throw_hresult_handler = nullptr; s_exceptionLoggerCalled = false; - co_await suspend_never(); + co_await std::suspend_never(); REQUIRE(false); co_return; diff --git a/test/test/when.cpp b/test/test/when.cpp index 35c9287a8..0b1151abc 100644 --- a/test/test/when.cpp +++ b/test/test/when.cpp @@ -5,13 +5,7 @@ using namespace concurrency; using namespace winrt; using namespace Windows::Foundation; -#ifdef __cpp_lib_coroutine -using std::suspend_never; -#else -using std::experimental::suspend_never; -#endif - -struct CommaStruct : suspend_never +struct CommaStruct : std::suspend_never { // If the comma operator is invoked, we will get a build failure. CommaStruct operator,(CommaStruct) = delete; diff --git a/test/test_nocoro/CMakeLists.txt b/test/test_nocoro/CMakeLists.txt new file mode 100644 index 000000000..ee234f146 --- /dev/null +++ b/test/test_nocoro/CMakeLists.txt @@ -0,0 +1,35 @@ +set(CMAKE_CXX_STANDARD 17) + +file(GLOB TEST_SRCS + LIST_DIRECTORIES false + CONFIGURE_DEPENDS + *.cpp +) +list(FILTER TEST_SRCS EXCLUDE REGEX "/(main|pch)\\.cpp") + + +list(APPEND BROKEN_TESTS + # No broken tests. +) + +# Exclude broken tests +foreach(TEST_SRCS_EXCLUDE_ITEM IN LISTS BROKEN_TESTS) + list(FILTER TEST_SRCS EXCLUDE REGEX "/${TEST_SRCS_EXCLUDE_ITEM}\\.cpp") +endforeach() + +add_executable(test_nocoro main.cpp ${TEST_SRCS}) + +target_compile_definitions(test_nocoro PRIVATE WINRT_NO_SOURCE_LOCATION) + +target_precompile_headers(test_nocoro PRIVATE pch.h) +set_source_files_properties( + main.cpp + PROPERTIES SKIP_PRECOMPILE_HEADERS true +) + +add_dependencies(test_nocoro build-cppwinrt-projection) + +add_test( + NAME test_nocoro + COMMAND "$" ${TEST_COLOR_ARG} +) diff --git a/test/test_nocoro/get.cpp b/test/test_nocoro/get.cpp new file mode 100644 index 000000000..11339e10b --- /dev/null +++ b/test/test_nocoro/get.cpp @@ -0,0 +1,74 @@ +#include "pch.h" + +using namespace winrt; +using namespace Windows::Foundation; + +template +struct async_completion_source : implements, IAsyncOperation, IAsyncInfo> +{ + void set_result(TResult result) + { + m_result = std::move(result); + m_status = AsyncStatus::Completed; + m_completed(*this, m_status); + } + + void Completed(AsyncOperationCompletedHandler completed) + { + m_completed = completed; + } + + AsyncOperationCompletedHandler Completed() const noexcept + { + return m_completed; + } + + TResult GetResults() + { + return m_result.value(); + } + + uint32_t Id() const + { + return 1; + } + + AsyncStatus Status() const + { + return m_status; + } + + hresult ErrorCode() const + { + return hresult(0); // S_OK + } + + void Cancel() const + { + throw hresult_error(0x80070032); // E_NOT_SUPPORTED + } + + void Close() const + { + } + +private: + AsyncStatus m_status = AsyncStatus::Started; + AsyncOperationCompletedHandler m_completed; + std::optional m_result; +}; + +TEST_CASE("get") +{ + auto acs = winrt::make_self>(); + + std::thread worker([acs] + { + std::this_thread::sleep_for(1s); + acs->set_result(0xDEADBEEF); + }); + + worker.detach(); + + REQUIRE(acs.as>().get() == 0xDEADBEEF); +} diff --git a/test/test_nocoro/main.cpp b/test/test_nocoro/main.cpp new file mode 100644 index 000000000..7590df7e1 --- /dev/null +++ b/test/test_nocoro/main.cpp @@ -0,0 +1,22 @@ +#include +#define CATCH_CONFIG_RUNNER +#include "catch.hpp" +#include "winrt/base.h" + +using namespace winrt; + +int main(int const argc, char** argv) +{ + init_apartment(); + std::set_terminate([] { reportFatal("Abnormal termination"); ExitProcess(1); }); + _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); + _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); + (void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); + return Catch::Session().run(argc, argv); +} + +CATCH_TRANSLATE_EXCEPTION(hresult_error const& e) +{ + return to_string(e.message()); +} diff --git a/test/test_nocoro/pch.cpp b/test/test_nocoro/pch.cpp new file mode 100644 index 000000000..1d9f38c57 --- /dev/null +++ b/test/test_nocoro/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/test/test_nocoro/pch.h b/test/test_nocoro/pch.h new file mode 100644 index 000000000..7ff48a37c --- /dev/null +++ b/test/test_nocoro/pch.h @@ -0,0 +1,6 @@ +#pragma once + +#include "catch.hpp" +#include "winrt/Windows.Foundation.h" + +using namespace std::literals; diff --git a/test/test_nocoro/test_nocoro.vcxproj b/test/test_nocoro/test_nocoro.vcxproj new file mode 100644 index 000000000..7efc28066 --- /dev/null +++ b/test/test_nocoro/test_nocoro.vcxproj @@ -0,0 +1,241 @@ + + + + + Debug + ARM64 + + + Debug + Win32 + + + Release + ARM64 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {9E392830-805A-4AAF-932D-C493143EFACA} + unittests + test_nocoro + false + + + + Application + true + + + Application + true + + + Application + false + true + + + Application + false + true + + + Application + true + + + Application + false + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + Disabled + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreadedDebug + Level4 + true + + + Console + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + MaxSpeed + true + true + $(OutputPath);Generated Files;..\ + NOMINMAX;_MBCS;%(PreprocessorDefinitions) + MultiThreaded + Level4 + true + + + Console + true + true + + + + + + + + + + + + + + + + + NotUsing + + + Create + + + + + + \ No newline at end of file