diff --git a/.gitattributes b/.gitattributes index 63f63314..da11d678 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ * text=auto * text eol=lf *.png -text -*.onnx -text \ No newline at end of file +*.onnx -text +*.winmd -text diff --git a/src/test/cpp/CMakeLists.txt b/src/test/cpp/CMakeLists.txt index fe203de6..f92bd794 100644 --- a/src/test/cpp/CMakeLists.txt +++ b/src/test/cpp/CMakeLists.txt @@ -82,17 +82,17 @@ add_custom_command(OUTPUT ${generated_files} ) add_custom_command(OUTPUT ${component_winmd} - COMMAND midlrt ${project_folder}\\component.idl /nomidl /winrt /winmd ${component_winmd} /metadata_dir ${project_folder} /reference ${project_folder}\\windows.winmd /h "nul" + COMMAND midlrt ${project_folder}\\component.idl /nomidl /winrt /winmd ${component_winmd} /metadata_dir ${project_folder}\\metadata /reference ${project_folder}\\metadata\\Windows.Foundation.winmd /h "nul" DEPENDS ${project_folder}\\component.idl ${generated_files} ) add_custom_command(OUTPUT ${foundation_h} - COMMAND ${cpp_exe} -in ${project_folder}\\windows.winmd -out ${generated_files} -verbose + COMMAND ${cpp_exe} -in local -out ${generated_files} -verbose DEPENDS ${component_winmd} ${generated_files} cppwinrt ) add_custom_command(OUTPUT ${mogule_g_cpp} - COMMAND ${cpp_exe} -in ${component_winmd} -ref ${project_folder}\\windows.winmd -include Component -out ${generated_files} -component -verbose -prefix -base -lib test -opt + COMMAND ${cpp_exe} -in ${component_winmd} -ref local -include Component -out ${generated_files} -component -verbose -prefix -base -lib test -opt DEPENDS ${foundation_h} ${generated_files} cppwinrt ) diff --git a/src/test/cpp/metadata/Windows.AI.winmd b/src/test/cpp/metadata/Windows.AI.winmd new file mode 100644 index 00000000..dae67806 Binary files /dev/null and b/src/test/cpp/metadata/Windows.AI.winmd differ diff --git a/src/test/cpp/metadata/Windows.ApplicationModel.winmd b/src/test/cpp/metadata/Windows.ApplicationModel.winmd new file mode 100644 index 00000000..f6f126d2 Binary files /dev/null and b/src/test/cpp/metadata/Windows.ApplicationModel.winmd differ diff --git a/src/test/cpp/metadata/Windows.Data.winmd b/src/test/cpp/metadata/Windows.Data.winmd new file mode 100644 index 00000000..93eb168b Binary files /dev/null and b/src/test/cpp/metadata/Windows.Data.winmd differ diff --git a/src/test/cpp/metadata/Windows.Devices.winmd b/src/test/cpp/metadata/Windows.Devices.winmd new file mode 100644 index 00000000..0f0a83e4 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Devices.winmd differ diff --git a/src/test/cpp/metadata/Windows.Foundation.winmd b/src/test/cpp/metadata/Windows.Foundation.winmd new file mode 100644 index 00000000..86fc9669 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Foundation.winmd differ diff --git a/src/test/cpp/metadata/Windows.Gaming.winmd b/src/test/cpp/metadata/Windows.Gaming.winmd new file mode 100644 index 00000000..9ad61a3c Binary files /dev/null and b/src/test/cpp/metadata/Windows.Gaming.winmd differ diff --git a/src/test/cpp/metadata/Windows.Globalization.winmd b/src/test/cpp/metadata/Windows.Globalization.winmd new file mode 100644 index 00000000..7b473dbb Binary files /dev/null and b/src/test/cpp/metadata/Windows.Globalization.winmd differ diff --git a/src/test/cpp/metadata/Windows.Graphics.winmd b/src/test/cpp/metadata/Windows.Graphics.winmd new file mode 100644 index 00000000..7468ffd8 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Graphics.winmd differ diff --git a/src/test/cpp/metadata/Windows.Management.winmd b/src/test/cpp/metadata/Windows.Management.winmd new file mode 100644 index 00000000..11c08a7c Binary files /dev/null and b/src/test/cpp/metadata/Windows.Management.winmd differ diff --git a/src/test/cpp/metadata/Windows.Media.winmd b/src/test/cpp/metadata/Windows.Media.winmd new file mode 100644 index 00000000..5db08825 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Media.winmd differ diff --git a/src/test/cpp/metadata/Windows.Networking.winmd b/src/test/cpp/metadata/Windows.Networking.winmd new file mode 100644 index 00000000..4a2cbf1e Binary files /dev/null and b/src/test/cpp/metadata/Windows.Networking.winmd differ diff --git a/src/test/cpp/metadata/Windows.Perception.winmd b/src/test/cpp/metadata/Windows.Perception.winmd new file mode 100644 index 00000000..198fb577 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Perception.winmd differ diff --git a/src/test/cpp/metadata/Windows.Security.winmd b/src/test/cpp/metadata/Windows.Security.winmd new file mode 100644 index 00000000..c5dbec81 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Security.winmd differ diff --git a/src/test/cpp/metadata/Windows.Services.winmd b/src/test/cpp/metadata/Windows.Services.winmd new file mode 100644 index 00000000..717b73ff Binary files /dev/null and b/src/test/cpp/metadata/Windows.Services.winmd differ diff --git a/src/test/cpp/metadata/Windows.Storage.winmd b/src/test/cpp/metadata/Windows.Storage.winmd new file mode 100644 index 00000000..7e043f74 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Storage.winmd differ diff --git a/src/test/cpp/metadata/Windows.System.winmd b/src/test/cpp/metadata/Windows.System.winmd new file mode 100644 index 00000000..cbff41b0 Binary files /dev/null and b/src/test/cpp/metadata/Windows.System.winmd differ diff --git a/src/test/cpp/metadata/Windows.UI.Xaml.winmd b/src/test/cpp/metadata/Windows.UI.Xaml.winmd new file mode 100644 index 00000000..f8961308 Binary files /dev/null and b/src/test/cpp/metadata/Windows.UI.Xaml.winmd differ diff --git a/src/test/cpp/metadata/Windows.UI.winmd b/src/test/cpp/metadata/Windows.UI.winmd new file mode 100644 index 00000000..43f3f401 Binary files /dev/null and b/src/test/cpp/metadata/Windows.UI.winmd differ diff --git a/src/test/cpp/metadata/Windows.Web.winmd b/src/test/cpp/metadata/Windows.Web.winmd new file mode 100644 index 00000000..e5143968 Binary files /dev/null and b/src/test/cpp/metadata/Windows.Web.winmd differ diff --git a/src/test/cpp/pch.h b/src/test/cpp/pch.h index f2b132ca..d856d435 100644 --- a/src/test/cpp/pch.h +++ b/src/test/cpp/pch.h @@ -1,7 +1,8 @@ #pragma once #include "catch.hpp" -#include "winrt/base.h" +#include "winrt/coroutine.h" + using namespace std::literals; template bool static_require() diff --git a/src/test/cpp/test/AsyncAutoCancel.cpp b/src/test/cpp/test/AsyncAutoCancel.cpp index c6d6c20c..83b9066a 100644 --- a/src/test/cpp/test/AsyncAutoCancel.cpp +++ b/src/test/cpp/test/AsyncAutoCancel.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncCancelCallback.cpp b/src/test/cpp/test/AsyncCancelCallback.cpp index 54161318..373c1560 100644 --- a/src/test/cpp/test/AsyncCancelCallback.cpp +++ b/src/test/cpp/test/AsyncCancelCallback.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncCheckCancel.cpp b/src/test/cpp/test/AsyncCheckCancel.cpp index 777fd8da..b442f723 100644 --- a/src/test/cpp/test/AsyncCheckCancel.cpp +++ b/src/test/cpp/test/AsyncCheckCancel.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncLocal.cpp b/src/test/cpp/test/AsyncLocal.cpp index e3f65010..8608d651 100644 --- a/src/test/cpp/test/AsyncLocal.cpp +++ b/src/test/cpp/test/AsyncLocal.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncProgress.cpp b/src/test/cpp/test/AsyncProgress.cpp index 2e8fa171..ef123a5e 100644 --- a/src/test/cpp/test/AsyncProgress.cpp +++ b/src/test/cpp/test/AsyncProgress.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncResult.cpp b/src/test/cpp/test/AsyncResult.cpp index 4cc96ec9..9ae36adb 100644 --- a/src/test/cpp/test/AsyncResult.cpp +++ b/src/test/cpp/test/AsyncResult.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncSuspend.cpp b/src/test/cpp/test/AsyncSuspend.cpp index 9bf833d1..1650e6f1 100644 --- a/src/test/cpp/test/AsyncSuspend.cpp +++ b/src/test/cpp/test/AsyncSuspend.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/AsyncThrow.cpp b/src/test/cpp/test/AsyncThrow.cpp index 9c0c3783..8e325df7 100644 --- a/src/test/cpp/test/AsyncThrow.cpp +++ b/src/test/cpp/test/AsyncThrow.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" using namespace winrt; using namespace Windows::Foundation; diff --git a/src/test/cpp/test/Interop.cpp b/src/test/cpp/test/Interop.cpp index 4da85b99..d744b697 100644 --- a/src/test/cpp/test/Interop.cpp +++ b/src/test/cpp/test/Interop.cpp @@ -1,6 +1,6 @@ #include "catch.hpp" #include -#include "winrt/Windows.Foundation.h" +#include "winrt/coroutine.h" struct __declspec(uuid("5040a5f4-796a-42ff-9f06-be89137a518f")) IBase : IUnknown { diff --git a/src/test/cpp/windows.winmd b/src/test/cpp/windows.winmd deleted file mode 100644 index 9999ff6d..00000000 Binary files a/src/test/cpp/windows.winmd and /dev/null differ diff --git a/src/tool/cpp/cppwinrt/code_writers.h b/src/tool/cpp/cppwinrt/code_writers.h index 81ec0a0f..a05f8d41 100644 --- a/src/tool/cpp/cppwinrt/code_writers.h +++ b/src/tool/cpp/cppwinrt/code_writers.h @@ -2871,11 +2871,7 @@ struct WINRT_EBO produce_dispatch_to_overridable w.write(strings::base_reference_produce); } - w.write(strings::base_await); - w.write(strings::base_std_async_action); - w.write(strings::base_std_async_action_with_progress); - w.write(strings::base_std_async_operation); - w.write(strings::base_std_async_operation_with_progress); + w.write(strings::base_async); } else if (namespace_name == "Windows.Foundation.Collections") { @@ -2893,9 +2889,5 @@ struct WINRT_EBO produce_dispatch_to_overridable { w.write(strings::base_xaml_typename); } - else if (namespace_name == "Windows.UI.Core") - { - w.write(strings::base_resume_foreground); - } } } diff --git a/src/tool/cpp/cppwinrt/file_writers.h b/src/tool/cpp/cppwinrt/file_writers.h index 8e2009d4..bdad4dfe 100644 --- a/src/tool/cpp/cppwinrt/file_writers.h +++ b/src/tool/cpp/cppwinrt/file_writers.h @@ -36,7 +36,6 @@ namespace xlang w.write(strings::base_chrono); w.write(strings::base_security); w.write(strings::base_std_hash); - w.write(strings::base_std_fire_and_forget); w.write(strings::base_reflect); w.write(strings::base_natvis); w.write(strings::base_version, XLANG_VERSION_STRING); @@ -45,6 +44,31 @@ namespace xlang w.flush_to_file(settings.output_folder + settings.root + "/base.h"); } + static void write_coroutine_h() + { + writer w; + write_license(w); + write_open_file_guard(w, "COROUTINE"); + + w.write(R"( +#include +#include "winrt/Windows.Foundation.h" +#include "winrt/Windows.System.h" +#include "winrt/Windows.UI.Core.h" +)"); + + w.write(strings::base_coroutine); + w.write(strings::base_coroutine_resume); + w.write(strings::base_coroutine_action); + w.write(strings::base_coroutine_action_with_progress); + w.write(strings::base_coroutine_operation); + w.write(strings::base_coroutine_operation_with_progress); + w.write(strings::base_std_fire_and_forget); + + write_close_file_guard(w); + w.flush_to_file(settings.output_folder + settings.root + "/coroutine.h"); + } + static void write_namespace_0_h(std::string_view const& ns, cache::namespace_members const& members) { writer w; diff --git a/src/tool/cpp/cppwinrt/main.cpp b/src/tool/cpp/cppwinrt/main.cpp index 60e77add..15e60974 100644 --- a/src/tool/cpp/cppwinrt/main.cpp +++ b/src/tool/cpp/cppwinrt/main.cpp @@ -212,6 +212,7 @@ namespace xlang if (settings.base) { write_base_h(); + write_coroutine_h(); } if (settings.component) diff --git a/src/tool/cpp/cppwinrt/strings/base_async.h b/src/tool/cpp/cppwinrt/strings/base_async.h new file mode 100644 index 00000000..a24df22f --- /dev/null +++ b/src/tool/cpp/cppwinrt/strings/base_async.h @@ -0,0 +1,31 @@ + +namespace winrt::impl +{ + inline bool is_sta() noexcept + { + int32_t aptType; + int32_t aptTypeQualifier; + return (error_ok == WINRT_CoGetApartmentType(&aptType, &aptTypeQualifier)) && ((aptType == 0 /*APTTYPE_STA*/) || (aptType == 3 /*APTTYPE_MAINSTA*/)); + } + + template + void blocking_suspend(Async const& async) + { + WINRT_ASSERT(!is_sta()); + + slim_mutex m; + slim_condition_variable cv; + bool completed = false; + async.Completed([&](auto && ...) + { + { + slim_lock_guard const guard(m); + completed = true; + } + cv.notify_one(); + }); + + slim_lock_guard guard(m); + cv.wait(m, [&] { return completed; }); + } +} diff --git a/src/tool/cpp/cppwinrt/strings/base_await.h b/src/tool/cpp/cppwinrt/strings/base_await.h deleted file mode 100644 index 048fd766..00000000 --- a/src/tool/cpp/cppwinrt/strings/base_await.h +++ /dev/null @@ -1,838 +0,0 @@ - -namespace winrt::impl -{ - inline bool is_sta() noexcept - { - int32_t aptType; - int32_t aptTypeQualifier; - return (error_ok == WINRT_CoGetApartmentType(&aptType, &aptTypeQualifier)) && ((aptType == 0 /*APTTYPE_STA*/) || (aptType == 3 /*APTTYPE_MAINSTA*/)); - } - - template - void blocking_suspend(Async const& async) - { - WINRT_ASSERT(!is_sta()); - - slim_mutex m; - slim_condition_variable cv; - bool completed = false; - async.Completed([&](auto&&...) - { - { - slim_lock_guard const guard(m); - completed = true; - } - cv.notify_one(); - }); - - slim_lock_guard guard(m); - cv.wait(m, [&] { return completed; }); - } - - template - struct await_adapter - { - Async const& async; - - bool await_ready() const - { - return async.Status() == Windows::Foundation::AsyncStatus::Completed; - } - - void await_suspend(std::experimental::coroutine_handle<> handle) const - { - auto context = capture(WINRT_CoGetObjectContext); - - async.Completed([handle, context = std::move(context)](auto const&, Windows::Foundation::AsyncStatus) - { - com_callback_args args{}; - args.data = handle.address(); - - auto callback = [](com_callback_args* args) noexcept -> int32_t - { - std::experimental::coroutine_handle<>::from_address(args->data)(); - return error_ok; - }; - - check_hresult(context->ContextCallback(callback, &args, guid_of(), 5, nullptr)); - }); - } - - auto await_resume() const - { - return async.GetResults(); - } - }; -} - -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED -namespace winrt::Windows::Foundation -{ - inline impl::await_adapter operator co_await(IAsyncAction const& async) - { - return{ async }; - } - - template - impl::await_adapter> operator co_await(IAsyncActionWithProgress const& async) - { - return{ async }; - } - - template - impl::await_adapter> operator co_await(IAsyncOperation const& async) - { - return{ async }; - } - - template - impl::await_adapter> operator co_await(IAsyncOperationWithProgress const& async) - { - return{ async }; - } -} -#endif - -namespace winrt -{ - [[nodiscard]] inline auto resume_background() - { - struct awaitable - { - bool await_ready() const noexcept - { - return false; - } - - void await_resume() const noexcept - { - } - - void await_suspend(std::experimental::coroutine_handle<> handle) const - { - if (!WINRT_TrySubmitThreadpoolCallback(callback, handle.address(), nullptr)) - { - throw_last_error(); - } - } - - private: - - static void WINRT_CALL callback(void*, void* context) noexcept - { - std::experimental::coroutine_handle<>::from_address(context)(); - } - }; - - return awaitable{}; - } - - template - [[nodiscard]] auto resume_background(T&& context) - { - struct awaitable - { - awaitable(T&& context) : m_context(std::forward(context)) - { - } - - bool await_ready() const noexcept - { - return false; - } - - void await_resume() const noexcept - { - } - - void await_suspend(std::experimental::coroutine_handle<> resume) - { - m_resume = resume; - - if (!WINRT_TrySubmitThreadpoolCallback(callback, this, nullptr)) - { - throw_last_error(); - } - } - - private: - - static void WINRT_CALL callback(void*, void* context) noexcept - { - auto that = static_cast(context); - auto guard = that->m_context(); - that->m_resume(); - } - - T&& m_context; - std::experimental::coroutine_handle<> m_resume{ nullptr }; - }; - - return awaitable{ std::forward(context) }; - } - - struct apartment_context - { - apartment_context() - { - m_context.capture(WINRT_CoGetObjectContext); - } - - bool await_ready() const noexcept - { - return false; - } - - void await_resume() const noexcept - { - } - - void await_suspend(std::experimental::coroutine_handle<> handle) const - { - impl::com_callback_args args{}; - args.data = handle.address(); - check_hresult(m_context->ContextCallback(callback, &args, guid_of(), 5, nullptr)); - } - - private: - - static int32_t WINRT_CALL callback(impl::com_callback_args* args) noexcept - { - std::experimental::coroutine_handle<>::from_address(args->data)(); - return impl::error_ok; - } - - com_ptr m_context; - }; - - [[nodiscard]] inline auto resume_after(Windows::Foundation::TimeSpan duration) - { - struct awaitable - { - explicit awaitable(Windows::Foundation::TimeSpan duration) noexcept : - m_duration(duration) - { - } - - bool await_ready() const noexcept - { - return m_duration.count() <= 0; - } - - void await_suspend(std::experimental::coroutine_handle<> handle) - { - m_timer.attach(check_pointer(WINRT_CreateThreadpoolTimer(callback, handle.address(), nullptr))); - int64_t relative_count = -m_duration.count(); - WINRT_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); - } - - void await_resume() const noexcept - { - } - - private: - - static void WINRT_CALL callback(void*, void* context, void*) noexcept - { - std::experimental::coroutine_handle<>::from_address(context)(); - } - - struct timer_traits - { - using type = impl::ptp_timer; - - static void close(type value) noexcept - { - WINRT_CloseThreadpoolTimer(value); - } - - static constexpr type invalid() noexcept - { - return nullptr; - } - }; - - handle_type m_timer; - Windows::Foundation::TimeSpan m_duration; - }; - - return awaitable{ duration }; - } - - [[nodiscard]] inline auto resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) - { - struct awaitable - { - awaitable(void* handle, Windows::Foundation::TimeSpan timeout) noexcept : - m_timeout(timeout), - m_handle(handle) - {} - - bool await_ready() const noexcept - { - return WINRT_WaitForSingleObject(m_handle, 0) == 0; - } - - void await_suspend(std::experimental::coroutine_handle<> resume) - { - m_resume = resume; - m_wait.attach(check_pointer(WINRT_CreateThreadpoolWait(callback, this, nullptr))); - int64_t relative_count = -m_timeout.count(); - int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; - WINRT_SetThreadpoolWait(m_wait.get(), m_handle, file_time); - } - - bool await_resume() const noexcept - { - return m_result == 0; - } - - private: - - static void WINRT_CALL callback(void*, void* context, void*, uint32_t result) noexcept - { - auto that = static_cast(context); - that->m_result = result; - that->m_resume(); - } - - struct wait_traits - { - using type = impl::ptp_wait; - - static void close(type value) noexcept - { - WINRT_CloseThreadpoolWait(value); - } - - static constexpr type invalid() noexcept - { - return nullptr; - } - }; - - handle_type m_wait; - Windows::Foundation::TimeSpan m_timeout; - void* m_handle; - uint32_t m_result{}; - std::experimental::coroutine_handle<> m_resume{ nullptr }; - }; - - return awaitable{ handle, timeout }; - } - - struct overlapped_io - { - uintptr_t Internal; - uintptr_t InternalHigh; - union - { - struct - { - uint32_t Offset; - uint32_t OffsetHigh; - } s; - void* Pointer; - }; - void* hEvent; - }; - - struct awaitable_base - { - static void WINRT_CALL callback(void*, void*, void* overlapped, uint32_t result, std::size_t, void*) noexcept - { - auto context = static_cast(overlapped); - context->m_result = result; - context->m_resume(); - } - - protected: - - overlapped_io m_overlapped{}; - uint32_t m_result{}; - std::experimental::coroutine_handle<> m_resume{ nullptr }; - }; - - struct resumable_io - { - resumable_io(void* object) : - m_io(check_pointer(WINRT_CreateThreadpoolIo(object, awaitable_base::callback, nullptr, nullptr))) - { - } - - template - auto start(F callback) - { - struct awaitable : awaitable_base, F - { - awaitable(impl::ptp_io io, F callback) noexcept : - F(callback), - m_io(io) - {} - - bool await_ready() const noexcept - { - return false; - } - - void await_suspend(std::experimental::coroutine_handle<> resume_handle) - { - m_resume = resume_handle; - WINRT_StartThreadpoolIo(m_io); - - try - { - (*this)(m_overlapped); - } - catch (...) - { - WINRT_CancelThreadpoolIo(m_io); - throw; - } - } - - uint32_t await_resume() const - { - if (m_result != 38 /*ERROR_HANDLE_EOF*/) - { - check_win32(m_result); - } - return static_cast(m_overlapped.InternalHigh); - } - - impl::ptp_io m_io{}; - }; - - return awaitable(get(), callback); - } - - template - auto start_pending(F callback) - { - struct awaitable : awaitable_base, F - { - awaitable(impl::ptp_io io, F callback) noexcept : - F(callback), - m_io(io) - {} - - bool await_ready() const noexcept - { - return false; - } - - bool await_suspend(std::experimental::coroutine_handle<> resume_handle) - { - m_resume = resume_handle; - WINRT_StartThreadpoolIo(m_io); - - try - { - bool const pending = (*this)(m_overlapped); - - if (!pending) - { - WINRT_CancelThreadpoolIo(m_io); - } - - return pending; - } - catch (...) - { - WINRT_CancelThreadpoolIo(m_io); - throw; - } - } - - uint32_t await_resume() const - { - if (m_result != 38 /*ERROR_HANDLE_EOF*/) - { - check_win32(m_result); - } - return static_cast(m_overlapped.InternalHigh); - } - - impl::ptp_io m_io{}; - }; - - return awaitable(get(), callback); - } - - impl::ptp_io get() const noexcept - { - return m_io.get(); - } - - private: - - struct io_traits - { - using type = impl::ptp_io; - - static void close(type value) noexcept - { - WINRT_CloseThreadpoolIo(value); - } - - static constexpr type invalid() noexcept - { - return nullptr; - } - }; - - handle_type m_io; - }; - -#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED - inline auto operator co_await(Windows::Foundation::TimeSpan duration) - { - return resume_after(duration); - } -#endif - - struct get_progress_token_t {}; - - inline get_progress_token_t get_progress_token() noexcept - { - return{}; - } - - struct get_cancellation_token_t {}; - - inline get_cancellation_token_t get_cancellation_token() noexcept - { - return{}; - } -} - -namespace winrt::impl -{ - template - struct cancellation_token - { - cancellation_token(Promise* promise) noexcept : m_promise(promise) - { - } - - bool await_ready() const noexcept - { - return true; - } - - void await_suspend(std::experimental::coroutine_handle<>) const noexcept - { - } - - cancellation_token await_resume() const noexcept - { - return*this; - } - - bool operator()() const noexcept - { - return m_promise->Status() == Windows::Foundation::AsyncStatus::Canceled; - } - - void callback(winrt::delegate<>&& cancel) noexcept - { - m_promise->cancellation_callback(std::move(cancel)); - } - - private: - - Promise * m_promise; - }; - - template - struct progress_token - { - progress_token(Promise* promise) noexcept : - m_promise(promise) - { - } - - bool await_ready() const noexcept - { - return true; - } - - void await_suspend(std::experimental::coroutine_handle<>) const noexcept - { - } - - progress_token await_resume() const noexcept - { - return*this; - } - - void operator()(Progress const& result) - { - m_promise->set_progress(result); - } - - private: - - Promise * m_promise; - }; - - template - struct promise_base : implements - { - using AsyncStatus = Windows::Foundation::AsyncStatus; - - unsigned long WINRT_CALL Release() noexcept - { - uint32_t const remaining = this->subtract_reference(); - - if (remaining == 0) - { - std::atomic_thread_fence(std::memory_order_acquire); - std::experimental::coroutine_handle::from_promise(*static_cast(this)).destroy(); - } - - return remaining; - } - - void Completed(CompletedHandler const& handler) - { - AsyncStatus status; - - { - slim_lock_guard const guard(m_lock); - - if (m_completed_assigned) - { - throw hresult_illegal_delegate_assignment(); - } - - m_completed_assigned = true; - - if (m_status == AsyncStatus::Started) - { - m_completed = make_agile_delegate(handler); - return; - } - - status = m_status; - } - - if (handler) - { - handler(*this, status); - } - } - - CompletedHandler Completed() noexcept - { - slim_lock_guard const guard(m_lock); - return m_completed; - } - - uint32_t Id() const noexcept - { - return 1; - } - - AsyncStatus Status() noexcept - { - slim_lock_guard const guard(m_lock); - return m_status; - } - - hresult ErrorCode() noexcept - { - try - { - slim_lock_guard const guard(m_lock); - rethrow_if_failed(); - return error_ok; - } - catch (...) - { - return to_hresult(); - } - } - - void Cancel() noexcept - { - winrt::delegate<> cancel; - - { - slim_lock_guard const guard(m_lock); - - if (m_status == AsyncStatus::Started) - { - m_status = AsyncStatus::Canceled; - m_exception = std::make_exception_ptr(hresult_canceled()); - cancel = std::move(m_cancel); - } - } - - if (cancel) - { - cancel(); - } - } - - void Close() const noexcept - { - } - - auto GetResults() - { - slim_lock_guard const guard(m_lock); - - if (m_status == AsyncStatus::Completed) - { - return static_cast(this)->get_return_value(); - } - - rethrow_if_failed(); - WINRT_ASSERT(m_status == AsyncStatus::Started); - throw hresult_illegal_method_call(); - } - - AsyncInterface get_return_object() const noexcept - { - return*this; - } - - void get_return_value() const noexcept - { - } - - void set_completed() noexcept - { - CompletedHandler handler; - AsyncStatus status; - - { - slim_lock_guard const guard(m_lock); - - if (m_status == AsyncStatus::Started) - { - m_status = AsyncStatus::Completed; - } - - handler = std::move(this->m_completed); - status = this->m_status; - } - - if (handler) - { - handler(*this, status); - } - } - - std::experimental::suspend_never initial_suspend() const noexcept - { - return{}; - } - - auto final_suspend() noexcept - { - struct awaiter - { - promise_base* promise; - - bool await_ready() const noexcept - { - return false; - } - - void await_resume() const noexcept - { - } - - bool await_suspend(std::experimental::coroutine_handle<>) const noexcept - { - promise->set_completed(); - uint32_t const remaining = promise->subtract_reference(); - - if (remaining == 0) - { - std::atomic_thread_fence(std::memory_order_acquire); - } - - return remaining > 0; - } - }; - - return awaiter{ this }; - } - - void unhandled_exception() noexcept - { - slim_lock_guard const guard(m_lock); - WINRT_ASSERT(m_status == AsyncStatus::Started || m_status == AsyncStatus::Canceled); - m_exception = std::current_exception(); - - try - { - std::rethrow_exception(m_exception); - } - catch (hresult_canceled const&) - { - m_status = AsyncStatus::Canceled; - } - catch (...) - { - m_status = AsyncStatus::Error; - } - } - - template - Expression&& await_transform(Expression&& expression) - { - if (Status() == AsyncStatus::Canceled) - { - throw winrt::hresult_canceled(); - } - - return std::forward(expression); - } - - cancellation_token await_transform(get_cancellation_token_t) noexcept - { - return{ static_cast(this) }; - } - - progress_token await_transform(get_progress_token_t) noexcept - { - return{ static_cast(this) }; - } - - void cancellation_callback(winrt::delegate<>&& cancel) noexcept - { - { - slim_lock_guard const guard(m_lock); - - if (m_status != AsyncStatus::Canceled) - { - m_cancel = std::move(cancel); - return; - } - } - - cancel(); - } - - protected: - - void rethrow_if_failed() const - { - if (m_status == AsyncStatus::Error || m_status == AsyncStatus::Canceled) - { - std::rethrow_exception(m_exception); - } - } - - std::exception_ptr m_exception{}; - slim_mutex m_lock; - CompletedHandler m_completed; - winrt::delegate<> m_cancel; - AsyncStatus m_status{ AsyncStatus::Started }; - bool m_completed_assigned{ false }; - }; -} diff --git a/src/tool/cpp/cppwinrt/strings/base_coroutine.h b/src/tool/cpp/cppwinrt/strings/base_coroutine.h new file mode 100644 index 00000000..a75c2a4f --- /dev/null +++ b/src/tool/cpp/cppwinrt/strings/base_coroutine.h @@ -0,0 +1,414 @@ + +namespace winrt::impl +{ + template + struct await_adapter + { + Async const& async; + + bool await_ready() const + { + return async.Status() == Windows::Foundation::AsyncStatus::Completed; + } + + void await_suspend(std::experimental::coroutine_handle<> handle) const + { + auto context = capture(WINRT_CoGetObjectContext); + + async.Completed([handle, context = std::move(context)](auto const&, Windows::Foundation::AsyncStatus) + { + com_callback_args args{}; + args.data = handle.address(); + + auto callback = [](com_callback_args* args) noexcept -> int32_t + { + std::experimental::coroutine_handle<>::from_address(args->data)(); + return error_ok; + }; + + check_hresult(context->ContextCallback(callback, &args, guid_of(), 5, nullptr)); + }); + } + + auto await_resume() const + { + return async.GetResults(); + } + }; +} + +#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED +namespace winrt::Windows::Foundation +{ + inline impl::await_adapter operator co_await(IAsyncAction const& async) + { + return{ async }; + } + + template + impl::await_adapter> operator co_await(IAsyncActionWithProgress const& async) + { + return{ async }; + } + + template + impl::await_adapter> operator co_await(IAsyncOperation const& async) + { + return{ async }; + } + + template + impl::await_adapter> operator co_await(IAsyncOperationWithProgress const& async) + { + return{ async }; + } +} +#endif + +namespace winrt +{ + struct get_progress_token_t {}; + + inline get_progress_token_t get_progress_token() noexcept + { + return{}; + } + + struct get_cancellation_token_t {}; + + inline get_cancellation_token_t get_cancellation_token() noexcept + { + return{}; + } +} + +namespace winrt::impl +{ + template + struct cancellation_token + { + cancellation_token(Promise* promise) noexcept : m_promise(promise) + { + } + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(std::experimental::coroutine_handle<>) const noexcept + { + } + + cancellation_token await_resume() const noexcept + { + return *this; + } + + bool operator()() const noexcept + { + return m_promise->Status() == Windows::Foundation::AsyncStatus::Canceled; + } + + void callback(winrt::delegate<>&& cancel) noexcept + { + m_promise->cancellation_callback(std::move(cancel)); + } + + private: + + Promise* m_promise; + }; + + template + struct progress_token + { + progress_token(Promise* promise) noexcept : + m_promise(promise) + { + } + + bool await_ready() const noexcept + { + return true; + } + + void await_suspend(std::experimental::coroutine_handle<>) const noexcept + { + } + + progress_token await_resume() const noexcept + { + return *this; + } + + void operator()(Progress const& result) + { + m_promise->set_progress(result); + } + + private: + + Promise* m_promise; + }; + + template + struct promise_base : implements + { + using AsyncStatus = Windows::Foundation::AsyncStatus; + + unsigned long WINRT_CALL Release() noexcept + { + uint32_t const remaining = this->subtract_reference(); + + if (remaining == 0) + { + std::atomic_thread_fence(std::memory_order_acquire); + std::experimental::coroutine_handle::from_promise(*static_cast(this)).destroy(); + } + + return remaining; + } + + void Completed(CompletedHandler const& handler) + { + AsyncStatus status; + + { + slim_lock_guard const guard(m_lock); + + if (m_completed_assigned) + { + throw hresult_illegal_delegate_assignment(); + } + + m_completed_assigned = true; + + if (m_status == AsyncStatus::Started) + { + m_completed = make_agile_delegate(handler); + return; + } + + status = m_status; + } + + if (handler) + { + handler(*this, status); + } + } + + CompletedHandler Completed() noexcept + { + slim_lock_guard const guard(m_lock); + return m_completed; + } + + uint32_t Id() const noexcept + { + return 1; + } + + AsyncStatus Status() noexcept + { + slim_lock_guard const guard(m_lock); + return m_status; + } + + hresult ErrorCode() noexcept + { + try + { + slim_lock_guard const guard(m_lock); + rethrow_if_failed(); + return error_ok; + } + catch (...) + { + return to_hresult(); + } + } + + void Cancel() noexcept + { + winrt::delegate<> cancel; + + { + slim_lock_guard const guard(m_lock); + + if (m_status == AsyncStatus::Started) + { + m_status = AsyncStatus::Canceled; + m_exception = std::make_exception_ptr(hresult_canceled()); + cancel = std::move(m_cancel); + } + } + + if (cancel) + { + cancel(); + } + } + + void Close() const noexcept + { + } + + auto GetResults() + { + slim_lock_guard const guard(m_lock); + + if (m_status == AsyncStatus::Completed) + { + return static_cast(this)->get_return_value(); + } + + rethrow_if_failed(); + WINRT_ASSERT(m_status == AsyncStatus::Started); + throw hresult_illegal_method_call(); + } + + AsyncInterface get_return_object() const noexcept + { + return *this; + } + + void get_return_value() const noexcept + { + } + + void set_completed() noexcept + { + CompletedHandler handler; + AsyncStatus status; + + { + slim_lock_guard const guard(m_lock); + + if (m_status == AsyncStatus::Started) + { + m_status = AsyncStatus::Completed; + } + + handler = std::move(this->m_completed); + status = this->m_status; + } + + if (handler) + { + handler(*this, status); + } + } + + std::experimental::suspend_never initial_suspend() const noexcept + { + return{}; + } + + auto final_suspend() noexcept + { + struct awaiter + { + promise_base* promise; + + bool await_ready() const noexcept + { + return false; + } + + void await_resume() const noexcept + { + } + + bool await_suspend(std::experimental::coroutine_handle<>) const noexcept + { + promise->set_completed(); + uint32_t const remaining = promise->subtract_reference(); + + if (remaining == 0) + { + std::atomic_thread_fence(std::memory_order_acquire); + } + + return remaining > 0; + } + }; + + return awaiter{ this }; + } + + void unhandled_exception() noexcept + { + slim_lock_guard const guard(m_lock); + WINRT_ASSERT(m_status == AsyncStatus::Started || m_status == AsyncStatus::Canceled); + m_exception = std::current_exception(); + + try + { + std::rethrow_exception(m_exception); + } + catch (hresult_canceled const&) + { + m_status = AsyncStatus::Canceled; + } + catch (...) + { + m_status = AsyncStatus::Error; + } + } + + template + Expression&& await_transform(Expression&& expression) + { + if (Status() == AsyncStatus::Canceled) + { + throw winrt::hresult_canceled(); + } + + return std::forward(expression); + } + + cancellation_token await_transform(get_cancellation_token_t) noexcept + { + return{ static_cast(this) }; + } + + progress_token await_transform(get_progress_token_t) noexcept + { + return{ static_cast(this) }; + } + + void cancellation_callback(winrt::delegate<>&& cancel) noexcept + { + { + slim_lock_guard const guard(m_lock); + + if (m_status != AsyncStatus::Canceled) + { + m_cancel = std::move(cancel); + return; + } + } + + cancel(); + } + + protected: + + void rethrow_if_failed() const + { + if (m_status == AsyncStatus::Error || m_status == AsyncStatus::Canceled) + { + std::rethrow_exception(m_exception); + } + } + + std::exception_ptr m_exception{}; + slim_mutex m_lock; + CompletedHandler m_completed; + winrt::delegate<> m_cancel; + AsyncStatus m_status{ AsyncStatus::Started }; + bool m_completed_assigned{ false }; + }; +} diff --git a/src/tool/cpp/cppwinrt/strings/base_std_async_action.h b/src/tool/cpp/cppwinrt/strings/base_coroutine_action.h similarity index 100% rename from src/tool/cpp/cppwinrt/strings/base_std_async_action.h rename to src/tool/cpp/cppwinrt/strings/base_coroutine_action.h diff --git a/src/tool/cpp/cppwinrt/strings/base_std_async_action_with_progress.h b/src/tool/cpp/cppwinrt/strings/base_coroutine_action_with_progress.h similarity index 100% rename from src/tool/cpp/cppwinrt/strings/base_std_async_action_with_progress.h rename to src/tool/cpp/cppwinrt/strings/base_coroutine_action_with_progress.h diff --git a/src/tool/cpp/cppwinrt/strings/base_std_async_operation.h b/src/tool/cpp/cppwinrt/strings/base_coroutine_operation.h similarity index 100% rename from src/tool/cpp/cppwinrt/strings/base_std_async_operation.h rename to src/tool/cpp/cppwinrt/strings/base_coroutine_operation.h diff --git a/src/tool/cpp/cppwinrt/strings/base_std_async_operation_with_progress.h b/src/tool/cpp/cppwinrt/strings/base_coroutine_operation_with_progress.h similarity index 100% rename from src/tool/cpp/cppwinrt/strings/base_std_async_operation_with_progress.h rename to src/tool/cpp/cppwinrt/strings/base_coroutine_operation_with_progress.h diff --git a/src/tool/cpp/cppwinrt/strings/base_coroutine_resume.h b/src/tool/cpp/cppwinrt/strings/base_coroutine_resume.h new file mode 100644 index 00000000..bb1a3de3 --- /dev/null +++ b/src/tool/cpp/cppwinrt/strings/base_coroutine_resume.h @@ -0,0 +1,314 @@ + +namespace winrt +{ + [[nodiscard]] inline auto resume_background() noexcept + { + struct awaitable + { + bool await_ready() const noexcept + { + return false; + } + + void await_resume() const noexcept + { + } + + void await_suspend(std::experimental::coroutine_handle<> handle) const + { + if (!WINRT_TrySubmitThreadpoolCallback(callback, handle.address(), nullptr)) + { + throw_last_error(); + } + } + + private: + + static void WINRT_CALL callback(void*, void* context) noexcept + { + std::experimental::coroutine_handle<>::from_address(context)(); + } + }; + + return awaitable{}; + } + + template + [[nodiscard]] auto resume_background(T const& context) noexcept + { + struct awaitable + { + awaitable(T const& context) : m_context(context) + { + } + + bool await_ready() const noexcept + { + return false; + } + + void await_resume() const noexcept + { + } + + void await_suspend(std::experimental::coroutine_handle<> resume) + { + m_resume = resume; + + if (!WINRT_TrySubmitThreadpoolCallback(callback, this, nullptr)) + { + throw_last_error(); + } + } + + private: + + static void WINRT_CALL callback(void*, void* context) noexcept + { + auto that = static_cast(context); + auto guard = that->m_context(); + that->m_resume(); + } + + T const& m_context; + std::experimental::coroutine_handle<> m_resume{ nullptr }; + }; + + return awaitable{ context }; + } + + struct apartment_context + { + apartment_context() + { + m_context.capture(WINRT_CoGetObjectContext); + } + + bool await_ready() const noexcept + { + return false; + } + + void await_resume() const noexcept + { + } + + void await_suspend(std::experimental::coroutine_handle<> handle) const + { + impl::com_callback_args args{}; + args.data = handle.address(); + check_hresult(m_context->ContextCallback(callback, &args, guid_of(), 5, nullptr)); + } + + private: + + static int32_t WINRT_CALL callback(impl::com_callback_args* args) noexcept + { + std::experimental::coroutine_handle<>::from_address(args->data)(); + return impl::error_ok; + } + + com_ptr m_context; + }; + + [[nodiscard]] inline auto resume_after(Windows::Foundation::TimeSpan duration) noexcept + { + struct awaitable + { + explicit awaitable(Windows::Foundation::TimeSpan duration) noexcept : + m_duration(duration) + { + } + + bool await_ready() const noexcept + { + return m_duration.count() <= 0; + } + + void await_suspend(std::experimental::coroutine_handle<> handle) + { + m_timer.attach(check_pointer(WINRT_CreateThreadpoolTimer(callback, handle.address(), nullptr))); + int64_t relative_count = -m_duration.count(); + WINRT_SetThreadpoolTimer(m_timer.get(), &relative_count, 0, 0); + } + + void await_resume() const noexcept + { + } + + private: + + static void WINRT_CALL callback(void*, void* context, void*) noexcept + { + std::experimental::coroutine_handle<>::from_address(context)(); + } + + struct timer_traits + { + using type = impl::ptp_timer; + + static void close(type value) noexcept + { + WINRT_CloseThreadpoolTimer(value); + } + + static constexpr type invalid() noexcept + { + return nullptr; + } + }; + + handle_type m_timer; + Windows::Foundation::TimeSpan m_duration; + }; + + return awaitable{ duration }; + } + + inline auto operator co_await(Windows::Foundation::TimeSpan duration) + { + return resume_after(duration); + } + + [[nodiscard]] inline auto resume_on_signal(void* handle, Windows::Foundation::TimeSpan timeout = {}) noexcept + { + struct awaitable + { + awaitable(void* handle, Windows::Foundation::TimeSpan timeout) noexcept : + m_timeout(timeout), + m_handle(handle) + {} + + bool await_ready() const noexcept + { + return WINRT_WaitForSingleObject(m_handle, 0) == 0; + } + + void await_suspend(std::experimental::coroutine_handle<> resume) + { + m_resume = resume; + m_wait.attach(check_pointer(WINRT_CreateThreadpoolWait(callback, this, nullptr))); + int64_t relative_count = -m_timeout.count(); + int64_t* file_time = relative_count != 0 ? &relative_count : nullptr; + WINRT_SetThreadpoolWait(m_wait.get(), m_handle, file_time); + } + + bool await_resume() const noexcept + { + return m_result == 0; + } + + private: + + static void WINRT_CALL callback(void*, void* context, void*, uint32_t result) noexcept + { + auto that = static_cast(context); + that->m_result = result; + that->m_resume(); + } + + struct wait_traits + { + using type = impl::ptp_wait; + + static void close(type value) noexcept + { + WINRT_CloseThreadpoolWait(value); + } + + static constexpr type invalid() noexcept + { + return nullptr; + } + }; + + handle_type m_wait; + Windows::Foundation::TimeSpan m_timeout; + void* m_handle; + uint32_t m_result{}; + std::experimental::coroutine_handle<> m_resume{ nullptr }; + }; + + return awaitable{ handle, timeout }; + } + + [[nodiscard]] inline auto resume_foreground( + Windows::UI::Core::CoreDispatcher const& dispatcher, + Windows::UI::Core::CoreDispatcherPriority const priority = Windows::UI::Core::CoreDispatcherPriority::Normal) noexcept + { + struct awaitable + { + awaitable(Windows::UI::Core::CoreDispatcher const& dispatcher, Windows::UI::Core::CoreDispatcherPriority const priority) noexcept : + m_dispatcher(dispatcher), + m_priority(priority) + { + } + + bool await_ready() const + { + return m_dispatcher.HasThreadAccess(); + } + + void await_resume() const noexcept + { + } + + void await_suspend(std::experimental::coroutine_handle<> handle) const + { + m_dispatcher.RunAsync(m_priority, [handle] + { + handle(); + }); + } + + private: + + Windows::UI::Core::CoreDispatcher const& m_dispatcher; + Windows::UI::Core::CoreDispatcherPriority const m_priority; + }; + + return awaitable{ dispatcher, priority }; + }; + + [[nodiscard]] inline auto resume_foreground( + Windows::System::DispatcherQueue const& dispatcher, + Windows::System::DispatcherQueuePriority const priority = Windows::System::DispatcherQueuePriority::Normal) noexcept + { + struct awaitable + { + awaitable(Windows::System::DispatcherQueue const& dispatcher, Windows::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(std::experimental::coroutine_handle<> handle) + { + m_queued = m_dispatcher.TryEnqueue(m_priority, [handle] + { + handle(); + }); + + return m_queued; + } + + private: + + Windows::System::DispatcherQueue const& m_dispatcher; + Windows::System::DispatcherQueuePriority const m_priority; + bool m_queued{}; + }; + + return awaitable{ dispatcher, priority }; + }; +} diff --git a/src/tool/cpp/cppwinrt/strings/base_dependencies.h b/src/tool/cpp/cppwinrt/strings/base_dependencies.h index 251effc7..03dfd993 100644 --- a/src/tool/cpp/cppwinrt/strings/base_dependencies.h +++ b/src/tool/cpp/cppwinrt/strings/base_dependencies.h @@ -20,7 +20,6 @@ #include #include #include -#include #if __has_include() #define WINRT_NUMERICS diff --git a/src/tool/cpp/cppwinrt/strings/base_resume_foreground.h b/src/tool/cpp/cppwinrt/strings/base_resume_foreground.h deleted file mode 100644 index 774ebac3..00000000 --- a/src/tool/cpp/cppwinrt/strings/base_resume_foreground.h +++ /dev/null @@ -1,40 +0,0 @@ - -namespace winrt -{ - struct resume_foreground - { - explicit resume_foreground(Windows::UI::Core::CoreDispatcher&& dispatcher, Windows::UI::Core::CoreDispatcherPriority const priority = Windows::UI::Core::CoreDispatcherPriority::Normal) : - m_dispatcher(std::move(dispatcher)), - m_priority(priority) - { - } - - explicit resume_foreground(Windows::UI::Core::CoreDispatcher const& dispatcher, Windows::UI::Core::CoreDispatcherPriority const priority = Windows::UI::Core::CoreDispatcherPriority::Normal) : - m_dispatcher(dispatcher), - m_priority(priority) - { - } - - bool await_ready() const - { - return m_dispatcher.HasThreadAccess(); - } - - void await_resume() const noexcept - { - } - - void await_suspend(std::experimental::coroutine_handle<> handle) const - { - m_dispatcher.RunAsync(m_priority, [handle] - { - handle(); - }); - } - - private: - - Windows::UI::Core::CoreDispatcher const m_dispatcher; - Windows::UI::Core::CoreDispatcherPriority const m_priority; - }; -}