#pragma once #include "boost/asio/awaitable.hpp" #include "boost/asio/co_spawn.hpp" #include "boost/asio/deadline_timer.hpp" #include "boost/asio/detached.hpp" #include "boost/asio/io_context.hpp" #include "boost/asio/use_awaitable.hpp" #include #include #include namespace TOS { using namespace boost::asio::experimental::awaitable_operators; template using coro = boost::asio::awaitable; class AsyncSemaphore { boost::asio::deadline_timer Deadline; std::atomic Lock = 0; public: AsyncSemaphore( boost::asio::io_context& ioc) : Deadline(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin)) {} boost::asio::awaitable async_wait() { try { co_await Deadline.async_wait(boost::asio::use_awaitable); } catch(boost::system::system_error code) { if(code.code() != boost::system::errc::operation_canceled) throw; } co_await boost::asio::this_coro::throw_if_cancelled(); } boost::asio::awaitable async_wait(std::function predicate) { while(!predicate()) co_await async_wait(); } void notify_one() { Deadline.cancel_one(); } void notify_all() { Deadline.cancel(); } }; class IAsyncDestructible : public std::enable_shared_from_this { protected: boost::asio::any_io_executor IOC; boost::asio::deadline_timer DestructLine; virtual coro<> asyncDestructor() { DestructLine.cancel(); co_return; } public: IAsyncDestructible(boost::asio::any_io_executor ioc) : IOC(ioc), DestructLine(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin)) {} virtual ~IAsyncDestructible() {} coro> cancelable(coro<> &&c) { return std::move(c) || DestructLine.async_wait(boost::asio::use_awaitable); } template> static std::shared_ptr createShared(boost::asio::any_io_executor ioc, T *ptr) { return std::shared_ptr(ptr, [ioc = std::move(ioc)](IAsyncDestructible *ptr) { boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> { try { co_await ptr->asyncDestructor(); } catch(...) { } delete ptr; co_return; } (ptr), boost::asio::detached); }); } template> static std::shared_ptr makeShared(boost::asio::any_io_executor ioc, Args&& ... args) { std::shared_ptr(new T(ioc, std::forward(args)..., [ioc = std::move(ioc)](IAsyncDestructible *ptr) { boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> { try { co_await ptr->asyncDestructor(); } catch(...) { } delete ptr; co_return; } (ptr), boost::asio::detached); })); } }; }