Skip to content

Instantly share code, notes, and snippets.

@kennykerr
Created July 3, 2018 18:48
Show Gist options
  • Save kennykerr/2a5b5995d0b2d9a0b646218d6a6cecb7 to your computer and use it in GitHub Desktop.
Save kennykerr/2a5b5995d0b2d9a0b646218d6a6cecb7 to your computer and use it in GitHub Desktop.
#include <winrt/base.h>
#include <windows.h>
template <typename T>
struct completion_source
{
completion_source()
{
m_signal.attach(CreateEvent(nullptr, true, false, nullptr));
}
void set(T const& value)
{
m_value = value;
SetEvent(m_signal.get());
}
bool await_ready() const noexcept
{
return WaitForSingleObject(m_signal.get(), 0) == 0;
}
void await_suspend(std::experimental::coroutine_handle<> resume)
{
m_wait.attach(winrt::check_pointer(CreateThreadpoolWait(callback, resume.address(), nullptr)));
SetThreadpoolWait(m_wait.get(), m_signal.get(), nullptr);
}
T await_resume() const noexcept
{
return m_value;
}
private:
static void __stdcall callback(PTP_CALLBACK_INSTANCE, void* context, PTP_WAIT, TP_WAIT_RESULT) noexcept
{
std::experimental::coroutine_handle<>::from_address(context)();
}
struct wait_traits
{
using type = PTP_WAIT;
static void close(type value) noexcept
{
CloseThreadpoolWait(value);
}
static constexpr type invalid() noexcept
{
return nullptr;
}
};
winrt::handle m_signal;
winrt::handle_type<wait_traits> m_wait;
T m_value{};
};
using namespace std::literals;
using namespace winrt;
using namespace Windows::Foundation;
fire_and_forget CompleteInFiveSeconds(completion_source<bool>& source)
{
co_await 5s;
source.set(true);
}
IAsyncAction Async()
{
completion_source<bool> source;
CompleteInFiveSeconds(source);
co_await source;
}
struct App
{
completion_source<hstring> m_source;
IAsyncOperation<hstring> Async()
{
co_return co_await m_source;
}
fire_and_forget CompleteInFiveSeconds()
{
co_await 5s;
m_source.set(L"Hello world");
}
};
int main()
{
{
auto async = Async();
puts("waiting");
async.get();
puts("done");
}
{
App app;
auto async = app.Async();
app.CompleteInFiveSeconds();
puts("waiting");
auto message = async.get();
printf("%ls\n", message.c_str());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment