diff --git a/main.cpp b/main.cpp index 5cbc5a2..734c5a9 100644 --- a/main.cpp +++ b/main.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "ping_thread.hpp" #include "registration_thread.hpp" @@ -32,6 +33,61 @@ using namespace std::chrono_literals; +struct irc_promise; + +struct irc_coroutine : std::coroutine_handle { + using promise_type = irc_promise; +}; + +struct irc_promise { + std::exception_ptr exception_; + + irc_coroutine get_return_object() { return {irc_coroutine::from_promise(*this)}; } + std::suspend_never initial_suspend() noexcept { return {}; } + std::suspend_always final_suspend() noexcept { return {}; } + void return_void() {} + void unhandled_exception() { + exception_ = std::current_exception(); + } +}; + +struct wait_command { + Connection& connection_; + IrcCommand want_cmd_; + + const IrcMsg *result; + boost::signals2::connection ircmsg_connection_; + boost::signals2::connection disconnect_connection_; + + wait_command(Connection& connection, IrcCommand want_cmd) + : connection_{connection}, want_cmd_{want_cmd} {} + + bool await_ready() noexcept { return false; } + void await_suspend(std::coroutine_handle handle) { + ircmsg_connection_ = connection_.sig_ircmsg.connect([this, handle](auto cmd, auto &msg) { + if (cmd == want_cmd_) { + ircmsg_connection_.disconnect(); + disconnect_connection_.disconnect(); + result = &msg; + handle.resume(); + } + }); + disconnect_connection_ = connection_.sig_disconnect.connect([this, handle]() { + ircmsg_connection_.disconnect(); + disconnect_connection_.disconnect(); + handle.destroy(); // XXX + }); + } + const IrcMsg &await_resume() { return *result; } +}; + +irc_coroutine example(Connection& connection) { + auto & msg1 = co_await wait_command {connection, IrcCommand::RPL_WELCOME}; + std::cout << "WELCOME " << msg1.args[0] << "\n"; + auto & msg5 = co_await wait_command {connection, IrcCommand::RPL_ISUPPORT}; + std::cout << "ISUPPORT " << msg5.args[0] << "\n"; +} + auto start(boost::asio::io_context & io, Settings const& settings) -> void { auto const connection = std::make_shared(io); @@ -41,14 +97,7 @@ auto start(boost::asio::io_context & io, Settings const& settings) -> void SelfThread::start(*connection); auto const snote_thread = SnoteThread::start(*connection); -/* - WatchdogThread::start(*connection); - IrcParseThread::start(*connection); - CommandThread::start(*connection); - auto const priv_thread = PrivThread::start(*connection, "privs.toml"); - echo_thread(*connection, priv_thread); - -*/ + /* snote_thread->sig_snote.connect([](auto tag, auto &match) { std::cout << "SNOTE " << static_cast(tag) << std::endl; for (auto c : match.get_results()) @@ -56,6 +105,8 @@ auto start(boost::asio::io_context & io, Settings const& settings) -> void std::cout << " " << std::string_view{c.first, c.second} << std::endl; } }); + */ + auto logic = example(*connection); boost::asio::co_spawn( io,