Created
May 6, 2024 11:09
Coroutine Demo (Taken from Andreas Fertig Talk)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <concepts> | |
#include <coroutine> | |
#include <cstdlib> | |
#include <exception> | |
#include <iostream> | |
#include <source_location> | |
#include <string> | |
#include <utility> | |
struct Chat | |
{ | |
struct promise_type | |
{ | |
std::string _msgOut{}; | |
std::string _msgIn{}; | |
void* operator new(std::size_t sz) { | |
std::cout << " ---- " << std::source_location::current().function_name() << " : " << sz << "\n"; | |
return malloc(sz); | |
} | |
void operator delete(void* p) { | |
if (p) | |
free(p); | |
} | |
static void unhandled_exception() noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
} | |
Chat get_return_object() | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
return Chat{this}; | |
} | |
static std::suspend_always initial_suspend() noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
return {}; | |
} | |
std::suspend_always yield_value(std::string msg) noexcept | |
{ | |
_msgOut = std::move(msg); | |
return {}; | |
} | |
auto await_transform(std::string) noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
struct awaiter | |
{ | |
promise_type &pt; | |
static bool await_ready() noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
return true; | |
} | |
[[nodiscard]] std::string await_resume() const noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
return std::move(pt._msgIn); | |
} | |
static void await_suspend(std::coroutine_handle<> /*unused*/) noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
} | |
}; | |
return awaiter{*this}; | |
} | |
void return_value(std::string msg) noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
_msgOut = std::move(msg); | |
} | |
static std::suspend_always final_suspend() noexcept | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
return {}; | |
} | |
}; | |
using Handle = std::coroutine_handle<promise_type>; | |
Handle mCoroHdl{}; | |
explicit Chat(promise_type *p) : mCoroHdl(Handle::from_promise(*p)) | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
} | |
Chat(Chat &&rhs) noexcept : mCoroHdl(std::exchange(rhs.mCoroHdl, nullptr)) | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
} | |
~Chat() | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
if (mCoroHdl) | |
{ | |
mCoroHdl.destroy(); | |
} | |
} | |
[[nodiscard]] std::string listen() const | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
if (not mCoroHdl.done()) | |
{ | |
std::cout << " ---- not done\n"; | |
mCoroHdl.resume(); | |
} | |
return std::move(mCoroHdl.promise()._msgOut); | |
} | |
void answer(std::string msg) const | |
{ | |
std::cout << " ---- " << std::source_location::current().function_name() << "\n"; | |
mCoroHdl.promise()._msgIn = msg; | |
if (not mCoroHdl.done()) | |
{ | |
mCoroHdl.resume(); | |
} | |
} | |
}; | |
Chat Fun() | |
{ | |
std::cout << " -- Before Hello \n"; | |
co_yield std::string{"Hello\n"}; | |
std::cout << " -- After Hello \n"; | |
std::cout << co_await std::string{}; | |
std::cout << " -- Before Here \n"; | |
co_return std::string{"Here\n"}; | |
} | |
int main() | |
{ | |
std::cout << std::source_location::current().function_name() << "\n"; | |
Chat chat = Fun(); | |
std::cout << "After Fun() \n"; | |
std::cout << chat.listen(); | |
std::cout << "After chat.listen() \n"; | |
chat.answer("Where are you?\n"); | |
std::cout << "After chat.answer() \n"; | |
std::cout << chat.listen(); | |
std::cout << "After chat.listen() \n"; | |
std::exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Output: