#pragma once #include #include #include #include #include #include #include #include #include namespace AL { using namespace boost::asio::experimental::awaitable_operators; namespace asio = boost::asio; using tcp = asio::ip::tcp; template using coro = asio::awaitable; class AsyncObject { protected: asio::io_context &IOC; asio::deadline_timer WorkDeadline; public: AsyncObject(asio::io_context &ioc) : IOC(ioc), WorkDeadline(ioc, boost::posix_time::pos_infin) { } inline asio::io_context& EXEC() { return IOC; } protected: template void co_spawn(Coroutine &&coroutine) { asio::co_spawn(IOC, WorkDeadline.async_wait(asio::use_awaitable) || std::move(coroutine), asio::detached); } }; template class AsyncAtomic : public AsyncObject { protected: asio::deadline_timer Deadline; ValueType Value; boost::mutex Mtx; public: AsyncAtomic(asio::io_context &ioc, ValueType &&value) : AsyncObject(ioc), Deadline(ioc), Value(std::move(value)) { } AsyncAtomic& operator=(ValueType &&value) { boost::unique_lock lock(Mtx); Value = std::move(value); Deadline.expires_from_now(boost::posix_time::pos_infin); return *this; } operator ValueType() const { return Value; } ValueType operator*() const { return Value; } AsyncAtomic& operator++() { boost::unique_lock lock(Mtx); Value--; Deadline.expires_from_now(boost::posix_time::pos_infin); return *this; } AsyncAtomic& operator--() { boost::unique_lock lock(Mtx); Value--; Deadline.expires_from_now(boost::posix_time::pos_infin); return *this; } AsyncAtomic& operator+=(ValueType value) { boost::unique_lock lock(Mtx); Value += value; Deadline.expires_from_now(boost::posix_time::pos_infin); return *this; } AsyncAtomic& operator-=(ValueType value) { boost::unique_lock lock(Mtx); Value -= value; Deadline.expires_from_now(boost::posix_time::pos_infin); return *this; } void wait(ValueType oldValue) { while(true) { if(oldValue != Value) return; boost::unique_lock lock(Mtx); if(oldValue != Value) return; std::atomic_bool flag = false; Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); }); lock.unlock(); flag.wait(false); } } void await(ValueType needValue) { while(true) { if(needValue == Value) return; boost::unique_lock lock(Mtx); if(needValue == Value) return; std::atomic_bool flag = false; Deadline.async_wait([&](boost::system::error_code errc) { flag.store(true); }); lock.unlock(); flag.wait(false); } } coro<> async_wait(ValueType oldValue) { while(true) { if(oldValue != Value) co_return; boost::unique_lock lock(Mtx); if(oldValue != Value) co_return; auto coroutine = Deadline.async_wait(); lock.unlock(); try { co_await std::move(coroutine); } catch(...) {} } } coro<> async_await(ValueType needValue) { while(true) { if(needValue == Value) co_return; boost::unique_lock lock(Mtx); if(needValue == Value) co_return; auto coroutine = Deadline.async_wait(); lock.unlock(); try { co_await std::move(coroutine); } catch(...) {} } } }; }