TOSAsync
This commit is contained in:
@@ -41,7 +41,6 @@ struct PP_Content_ChunkRemove : public ParsedPacket {
|
|||||||
using namespace TOS;
|
using namespace TOS;
|
||||||
|
|
||||||
ServerSession::~ServerSession() {
|
ServerSession::~ServerSession() {
|
||||||
WorkDeadline.cancel();
|
|
||||||
UseLock.wait_no_use();
|
UseLock.wait_no_use();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -120,10 +120,18 @@ coro<> AsyncSocket::read(std::byte *data, uint32_t size) {
|
|||||||
void AsyncSocket::closeRead() {
|
void AsyncSocket::closeRead() {
|
||||||
if(Socket.is_open() && !ReadShutdowned) {
|
if(Socket.is_open() && !ReadShutdowned) {
|
||||||
ReadShutdowned = true;
|
ReadShutdowned = true;
|
||||||
|
// TODO:
|
||||||
try { Socket.shutdown(boost::asio::socket_base::shutdown_receive); } catch(...) {}
|
try { Socket.shutdown(boost::asio::socket_base::shutdown_receive); } catch(...) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AsyncSocket::close() {
|
||||||
|
if(Socket.is_open()) {
|
||||||
|
Socket.close();
|
||||||
|
ReadShutdowned = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
coro<> AsyncSocket::waitForSend() {
|
coro<> AsyncSocket::waitForSend() {
|
||||||
asio::deadline_timer waiter(IOC);
|
asio::deadline_timer waiter(IOC);
|
||||||
|
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ protected:
|
|||||||
|
|
||||||
coro<> read(std::byte *data, uint32_t size);
|
coro<> read(std::byte *data, uint32_t size);
|
||||||
void closeRead();
|
void closeRead();
|
||||||
|
void close();
|
||||||
|
|
||||||
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
template<typename T, std::enable_if_t<std::is_integral_v<T> or std::is_same_v<T, std::string>, int> = 0>
|
||||||
coro<T> read() {
|
coro<T> read() {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
ContentEventController::ContentEventController(std::unique_ptr<RemoteClient> &&remote)
|
ContentEventController::ContentEventController(RemoteClient_ptr &&remote)
|
||||||
: Remote(std::move(remote))
|
: Remote(std::move(remote))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
class RemoteClient;
|
class RemoteClient;
|
||||||
|
using RemoteClient_ptr = std::unique_ptr<RemoteClient, std::function<void(RemoteClient*)>>;
|
||||||
class GameServer;
|
class GameServer;
|
||||||
class World;
|
class World;
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Управляется сервером
|
// Управляется сервером
|
||||||
std::unique_ptr<RemoteClient> Remote;
|
RemoteClient_ptr Remote;
|
||||||
// Регионы сюда заглядывают
|
// Регионы сюда заглядывают
|
||||||
// Каждый такт значения изменений обновляются GameServer'ом
|
// Каждый такт значения изменений обновляются GameServer'ом
|
||||||
// Объявленная в чанках территория точно отслеживается (активная зона)
|
// Объявленная в чанках территория точно отслеживается (активная зона)
|
||||||
@@ -173,7 +174,7 @@ public:
|
|||||||
// std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> SubscribedRegions;
|
// std::unordered_map<WorldId_t, std::vector<Pos::GlobalRegion>> SubscribedRegions;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ContentEventController(std::unique_ptr<RemoteClient> &&remote);
|
ContentEventController(RemoteClient_ptr &&remote);
|
||||||
|
|
||||||
// Измеряется в чанках в радиусе (активная зона)
|
// Измеряется в чанках в радиусе (активная зона)
|
||||||
uint16_t getViewRangeActive() const;
|
uint16_t getViewRangeActive() const;
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ coro<> GameServer::pushSocketGameProtocol(tcp::socket socket, const std::string
|
|||||||
co_await Net::AsyncSocket::write<uint8_t>(socket, 0);
|
co_await Net::AsyncSocket::write<uint8_t>(socket, 0);
|
||||||
|
|
||||||
External.NewConnectedPlayers.lock_write()
|
External.NewConnectedPlayers.lock_write()
|
||||||
->push_back(std::make_unique<RemoteClient>(IOC, std::move(socket), username));
|
->push_back(RemoteClient::Create(IOC, std::move(socket), username));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,7 +333,7 @@ void GameServer::run() {
|
|||||||
// Отключить вновь подключившихся
|
// Отключить вновь подключившихся
|
||||||
auto lock = External.NewConnectedPlayers.lock_write();
|
auto lock = External.NewConnectedPlayers.lock_write();
|
||||||
|
|
||||||
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
for(RemoteClient_ptr &client : *lock) {
|
||||||
client->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
client->shutdown(EnumDisconnect::ByInterface, ShutdownReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,8 +449,7 @@ void GameServer::stepPlayers() {
|
|||||||
if(!External.NewConnectedPlayers.no_lock_readable().empty()) {
|
if(!External.NewConnectedPlayers.no_lock_readable().empty()) {
|
||||||
auto lock = External.NewConnectedPlayers.lock_write();
|
auto lock = External.NewConnectedPlayers.lock_write();
|
||||||
|
|
||||||
for(std::unique_ptr<RemoteClient> &client : *lock) {
|
for(RemoteClient_ptr &client : *lock) {
|
||||||
asio::co_spawn(IOC, client->run(), asio::detached);
|
|
||||||
Game.CECs.push_back(std::make_unique<ContentEventController>(std::move(client)));
|
Game.CECs.push_back(std::make_unique<ContentEventController>(std::move(client)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class GameServer {
|
|||||||
|
|
||||||
struct {
|
struct {
|
||||||
Lockable<std::set<std::string>> ConnectedPlayersSet;
|
Lockable<std::set<std::string>> ConnectedPlayersSet;
|
||||||
Lockable<std::list<std::unique_ptr<RemoteClient>>> NewConnectedPlayers;
|
Lockable<std::list<RemoteClient_ptr>> NewConnectedPlayers;
|
||||||
|
|
||||||
} External;
|
} External;
|
||||||
|
|
||||||
|
|||||||
@@ -3,28 +3,33 @@
|
|||||||
#include "Common/Net.hpp"
|
#include "Common/Net.hpp"
|
||||||
#include "Server/Abstract.hpp"
|
#include "Server/Abstract.hpp"
|
||||||
#include <boost/asio/error.hpp>
|
#include <boost/asio/error.hpp>
|
||||||
|
#include <boost/chrono/duration.hpp>
|
||||||
#include <boost/system/system_error.hpp>
|
#include <boost/system/system_error.hpp>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include "World.hpp"
|
#include "World.hpp"
|
||||||
|
#include "boost/asio/steady_timer.hpp"
|
||||||
#include <Common/Packets.hpp>
|
#include <Common/Packets.hpp>
|
||||||
|
|
||||||
|
|
||||||
namespace LV::Server {
|
namespace LV::Server {
|
||||||
|
|
||||||
RemoteClient::~RemoteClient() {
|
coro<> RemoteClient::asyncDestructor() {
|
||||||
shutdown(EnumDisconnect::ByInterface, "~RemoteClient()");
|
shutdown(EnumDisconnect::ByInterface, "~RemoteClient()");
|
||||||
if(Socket.isAlive()) {
|
asio::steady_timer deadline(IOC);
|
||||||
Socket.closeRead();
|
deadline.expires_after(std::chrono::seconds(1));
|
||||||
}
|
|
||||||
|
|
||||||
UseLock.wait_no_use();
|
Socket.closeRead();
|
||||||
|
co_await (deadline.async_wait(asio::use_awaitable) || RunCoro.async_wait());
|
||||||
|
Socket.close();
|
||||||
|
|
||||||
|
co_await deadline.async_wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
coro<> RemoteClient::run() {
|
RemoteClient::~RemoteClient() = default;
|
||||||
auto useLock = UseLock.lock();
|
|
||||||
|
|
||||||
|
coro<> RemoteClient::run() {
|
||||||
try {
|
try {
|
||||||
while(!IsGoingShutdown && IsConnected) {
|
while(!IsGoingShutdown && IsConnected) {
|
||||||
co_await readPacket(Socket);
|
co_await readPacket(Socket);
|
||||||
|
|||||||
@@ -3,12 +3,18 @@
|
|||||||
#include <TOSLib.hpp>
|
#include <TOSLib.hpp>
|
||||||
#include <Common/Lockable.hpp>
|
#include <Common/Lockable.hpp>
|
||||||
#include <Common/Net.hpp>
|
#include <Common/Net.hpp>
|
||||||
|
#include <Common/Async.hpp>
|
||||||
#include "Abstract.hpp"
|
#include "Abstract.hpp"
|
||||||
#include "Common/Packets.hpp"
|
#include "Common/Packets.hpp"
|
||||||
#include "Server/ContentEventController.hpp"
|
#include "Server/ContentEventController.hpp"
|
||||||
|
#include "TOSAsync.hpp"
|
||||||
|
#include "boost/asio/detached.hpp"
|
||||||
|
#include "boost/asio/io_context.hpp"
|
||||||
|
#include "boost/asio/use_awaitable.hpp"
|
||||||
#include <Common/Abstract.hpp>
|
#include <Common/Abstract.hpp>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@@ -173,16 +179,16 @@ using EntityKey = std::tuple<WorldId_c, Pos::GlobalRegion>;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RemoteClient;
|
||||||
|
using RemoteClient_ptr = std::unique_ptr<RemoteClient, std::function<void(RemoteClient*)>>;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Обработчик сокета клиента.
|
Обработчик сокета клиента.
|
||||||
Подписывает клиента на отслеживание необходимых ресурсов
|
Подписывает клиента на отслеживание необходимых ресурсов
|
||||||
на основе передаваемых клиенту данных
|
на основе передаваемых клиенту данных
|
||||||
*/
|
*/
|
||||||
class RemoteClient {
|
class RemoteClient : public TOS::IAsyncDestructible {
|
||||||
TOS::Logger LOG;
|
TOS::Logger LOG;
|
||||||
DestroyLock UseLock;
|
|
||||||
Net::AsyncSocket Socket;
|
Net::AsyncSocket Socket;
|
||||||
bool IsConnected = true, IsGoingShutdown = false;
|
bool IsConnected = true, IsGoingShutdown = false;
|
||||||
|
|
||||||
@@ -264,20 +270,32 @@ class RemoteClient {
|
|||||||
ResourceRequest NextRequest;
|
ResourceRequest NextRequest;
|
||||||
std::vector<Net::Packet> SimplePackets;
|
std::vector<Net::Packet> SimplePackets;
|
||||||
|
|
||||||
|
TOS::WaitableCoro RunCoro;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const std::string Username;
|
const std::string Username;
|
||||||
Pos::Object CameraPos = {0, 0, 0};
|
Pos::Object CameraPos = {0, 0, 0};
|
||||||
ToServer::PacketQuat CameraQuat = {0};
|
ToServer::PacketQuat CameraQuat = {0};
|
||||||
|
|
||||||
public:
|
private:
|
||||||
|
|
||||||
RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username)
|
RemoteClient(asio::io_context &ioc, tcp::socket socket, const std::string username)
|
||||||
: LOG("RemoteClient " + username), Socket(ioc, std::move(socket)), Username(username)
|
: IAsyncDestructible(ioc), LOG("RemoteClient " + username), Socket(ioc, std::move(socket)),
|
||||||
|
Username(username), RunCoro(ioc)
|
||||||
{
|
{
|
||||||
|
RunCoro.co_spawn(run());
|
||||||
}
|
}
|
||||||
|
|
||||||
~RemoteClient();
|
virtual coro<> asyncDestructor() override;
|
||||||
|
|
||||||
coro<> run();
|
coro<> run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static RemoteClient_ptr Create(asio::io_context &ioc, tcp::socket socket, const std::string username) {
|
||||||
|
return createUnique<>(ioc, new RemoteClient(ioc, std::move(socket), username));
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~RemoteClient();
|
||||||
|
|
||||||
void shutdown(EnumDisconnect type, const std::string reason);
|
void shutdown(EnumDisconnect type, const std::string reason);
|
||||||
bool isConnected() { return IsConnected; }
|
bool isConnected() { return IsConnected; }
|
||||||
|
|
||||||
|
|||||||
159
Src/TOSAsync.hpp
159
Src/TOSAsync.hpp
@@ -1,77 +1,136 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "boost/asio/awaitable.hpp"
|
#include "TOSLib.hpp"
|
||||||
#include "boost/asio/co_spawn.hpp"
|
#include "boost/asio/associated_cancellation_slot.hpp"
|
||||||
|
#include "boost/asio/associated_executor.hpp"
|
||||||
#include "boost/asio/deadline_timer.hpp"
|
#include "boost/asio/deadline_timer.hpp"
|
||||||
#include "boost/asio/detached.hpp"
|
|
||||||
#include "boost/asio/io_context.hpp"
|
#include "boost/asio/io_context.hpp"
|
||||||
#include "boost/asio/use_awaitable.hpp"
|
#include "boost/system/detail/error_code.hpp"
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/asio/detached.hpp>
|
||||||
#include <boost/asio/experimental/awaitable_operators.hpp>
|
#include <boost/asio/experimental/awaitable_operators.hpp>
|
||||||
|
#include <exception>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace TOS {
|
namespace TOS {
|
||||||
|
|
||||||
using namespace boost::asio::experimental::awaitable_operators;
|
using namespace boost::asio::experimental::awaitable_operators;
|
||||||
|
namespace asio = boost::asio;
|
||||||
template<typename T = void>
|
template<typename T = void>
|
||||||
using coro = boost::asio::awaitable<T>;
|
using coro = boost::asio::awaitable<T>;
|
||||||
|
|
||||||
class AsyncSemaphore
|
// class AsyncSemaphore
|
||||||
{
|
// {
|
||||||
boost::asio::deadline_timer Deadline;
|
// boost::asio::deadline_timer Deadline;
|
||||||
std::atomic<uint8_t> Lock = 0;
|
// std::atomic<uint8_t> Lock = 0;
|
||||||
|
|
||||||
|
// public:
|
||||||
|
// AsyncSemaphore(boost::asio::io_context& ioc)
|
||||||
|
// : Deadline(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin))
|
||||||
|
// {}
|
||||||
|
|
||||||
|
// coro<> 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 asio::this_coro::throw_if_cancelled();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// coro<> async_wait(std::function<bool()> predicate) {
|
||||||
|
// while(!predicate())
|
||||||
|
// co_await async_wait();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void notify_one() {
|
||||||
|
// Deadline.cancel_one();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// void notify_all() {
|
||||||
|
// Deadline.cancel();
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
/*
|
||||||
|
Многие могут уведомлять одного
|
||||||
|
Ждёт события. После доставки уведомления ждёт повторно
|
||||||
|
*/
|
||||||
|
class MultipleToOne_AsyncSymaphore {
|
||||||
|
asio::deadline_timer Timer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AsyncSemaphore(
|
MultipleToOne_AsyncSymaphore(asio::io_context &ioc)
|
||||||
boost::asio::io_context& ioc)
|
: Timer(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin))
|
||||||
: Deadline(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
boost::asio::awaitable<void> async_wait() {
|
void notify() {
|
||||||
try {
|
Timer.cancel();
|
||||||
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();
|
void wait() {
|
||||||
|
Timer.wait();
|
||||||
|
Timer.expires_at(boost::posix_time::ptime(boost::posix_time::pos_infin));
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::awaitable<void> async_wait(std::function<bool()> predicate) {
|
coro<> async_wait() {
|
||||||
while(!predicate())
|
try { co_await Timer.async_wait(); } catch(...) {}
|
||||||
co_await async_wait();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_one() {
|
};
|
||||||
Deadline.cancel_one();
|
|
||||||
|
class WaitableCoro {
|
||||||
|
asio::io_context &IOC;
|
||||||
|
std::shared_ptr<MultipleToOne_AsyncSymaphore> Symaphore;
|
||||||
|
std::exception_ptr LastException;
|
||||||
|
|
||||||
|
public:
|
||||||
|
WaitableCoro(asio::io_context &ioc)
|
||||||
|
: IOC(ioc)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template<typename Token>
|
||||||
|
void co_spawn(Token token) {
|
||||||
|
Symaphore = std::make_shared<MultipleToOne_AsyncSymaphore>(IOC);
|
||||||
|
asio::co_spawn(IOC, [token = std::move(token), symaphore = Symaphore]() -> coro<> {
|
||||||
|
co_await std::move(token);
|
||||||
|
symaphore->notify();
|
||||||
|
}, asio::detached);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify_all() {
|
void wait() {
|
||||||
Deadline.cancel();
|
Symaphore->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
coro<> async_wait() {
|
||||||
|
return Symaphore->async_wait();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Используется, чтобы вместо уничтожения объекта в умной ссылке, вызвать корутину с co_await asyncDestructor()
|
||||||
|
*/
|
||||||
class IAsyncDestructible : public std::enable_shared_from_this<IAsyncDestructible> {
|
class IAsyncDestructible : public std::enable_shared_from_this<IAsyncDestructible> {
|
||||||
protected:
|
protected:
|
||||||
boost::asio::any_io_executor IOC;
|
asio::io_context &IOC;
|
||||||
boost::asio::deadline_timer DestructLine;
|
|
||||||
|
|
||||||
virtual coro<> asyncDestructor() { DestructLine.cancel(); co_return; }
|
virtual coro<> asyncDestructor() { co_return; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IAsyncDestructible(boost::asio::any_io_executor ioc)
|
IAsyncDestructible(asio::io_context &ioc)
|
||||||
: IOC(ioc), DestructLine(ioc, boost::posix_time::ptime(boost::posix_time::pos_infin))
|
: IOC(ioc)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual ~IAsyncDestructible() {}
|
virtual ~IAsyncDestructible() {}
|
||||||
|
|
||||||
coro<std::variant<std::monostate, std::monostate>> cancelable(coro<> &&c) { return std::move(c) || DestructLine.async_wait(boost::asio::use_awaitable); }
|
protected:
|
||||||
|
|
||||||
template<typename T, typename = typename std::is_same<IAsyncDestructible, T>>
|
template<typename T, typename = typename std::is_same<IAsyncDestructible, T>>
|
||||||
static std::shared_ptr<T> createShared(boost::asio::any_io_executor ioc, T *ptr)
|
static std::shared_ptr<T> createShared(asio::io_context &ioc, T *ptr)
|
||||||
{
|
{
|
||||||
return std::shared_ptr<T>(ptr, [ioc = std::move(ioc)](IAsyncDestructible *ptr) {
|
return std::shared_ptr<T>(ptr, [&ioc = ioc](T *ptr) {
|
||||||
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
||||||
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
||||||
delete ptr;
|
delete ptr;
|
||||||
@@ -80,16 +139,40 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ...Args, typename = typename std::is_same<IAsyncDestructible, T>>
|
template<typename T, typename = typename std::is_same<IAsyncDestructible, T>>
|
||||||
static std::shared_ptr<T> makeShared(boost::asio::any_io_executor ioc, Args&& ... args)
|
static coro<std::shared_ptr<T>> createShared(T *ptr)
|
||||||
{
|
{
|
||||||
std::shared_ptr<T>(new T(ioc, std::forward<Args>(args)..., [ioc = std::move(ioc)](IAsyncDestructible *ptr) {
|
co_return std::shared_ptr<T>(ptr, [ioc = asio::get_associated_executor(co_await asio::this_coro::executor)](T *ptr) {
|
||||||
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
||||||
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
||||||
delete ptr;
|
delete ptr;
|
||||||
co_return;
|
co_return;
|
||||||
} (ptr), boost::asio::detached);
|
} (ptr), boost::asio::detached);
|
||||||
}));
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = typename std::is_same<IAsyncDestructible, T>>
|
||||||
|
static std::unique_ptr<T, std::function<void(T*)>> createUnique(asio::io_context &ioc, T *ptr)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<T, std::function<void(T*)>>(ptr, [&ioc = ioc](T *ptr) {
|
||||||
|
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
||||||
|
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
||||||
|
delete ptr;
|
||||||
|
co_return;
|
||||||
|
} (ptr), boost::asio::detached);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename = typename std::is_same<IAsyncDestructible, T>>
|
||||||
|
static coro<std::unique_ptr<T, std::function<void(T*)>>> createUnique(T *ptr)
|
||||||
|
{
|
||||||
|
co_return std::unique_ptr<T, std::function<void(T*)>>(ptr, [ioc = asio::get_associated_executor(co_await asio::this_coro::executor)](T *ptr) {
|
||||||
|
boost::asio::co_spawn(ioc, [](IAsyncDestructible *ptr) -> coro<> {
|
||||||
|
try { co_await ptr->asyncDestructor(); } catch(...) { }
|
||||||
|
delete ptr;
|
||||||
|
co_return;
|
||||||
|
} (ptr), boost::asio::detached);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user