/
Mr.Stalin
/
FOnline-Engine
Обзор
Документация
Войти
/
Mr.Stalin
/
FOnline-Engine
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Source/Server/NetworkServer-Interthread.cpp
167 строк
6 KB
cvet
Non const locals (#190)
24 июл 2026, 10:46
Не верифицирован
24 июл 2026, 10:46
4883d25
Код
Авторство
О чём код?
// __________ ___ ______ _ // / ____/ __ \____ / (_)___ ___ / ____/___ ____ _(_)___ ___ // / /_ / / / / __ \/ / / __ \/ _ \ / __/ / __ \/ __ `/ / __ \/ _ ` // / __/ / /_/ / / / / / / / / / __/ / /___/ / / / /_/ / / / / / __/ // /_/ \____/_/ /_/_/_/_/ /_/\___/ /_____/_/ /_/\__, /_/_/ /_/\___/ // /____/ // FOnline Engine // https://fonline.ru // https://github.com/cvet/fonline // // MIT License // // Copyright (c) 2006 - 2026, Anton Tsvetinskiy aka cvet <cvet@tut.by> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // #include "NetworkServer.h" FO_BEGIN_NAMESPACE class NetworkServerConnection_Interthread : public NetworkServerConnection { public: explicit NetworkServerConnection_Interthread(ptr<ServerNetworkSettings> settings, InterthreadDataCallback send); NetworkServerConnection_Interthread(const NetworkServerConnection_Interthread&) = delete; NetworkServerConnection_Interthread(NetworkServerConnection_Interthread&&) noexcept = delete; auto operator=(const NetworkServerConnection_Interthread&) = delete; auto operator=(NetworkServerConnection_Interthread&&) noexcept = delete; ~NetworkServerConnection_Interthread() override = default; void Receive(const_span<uint8_t> buf); private: void DispatchImpl() override; void DisconnectImpl() override; mutex _sendLocker {}; InterthreadDataCallback _send FO_TSA_GUARDED_BY(_sendLocker); }; class InterthreadServer : public NetworkServer { public: explicit InterthreadServer(ptr<ServerNetworkSettings> settings, NewConnectionCallback callback); InterthreadServer() = delete; InterthreadServer(const InterthreadServer&) = delete; InterthreadServer(InterthreadServer&&) noexcept = delete; auto operator=(const InterthreadServer&) = delete; auto operator=(InterthreadServer&&) noexcept = delete; ~InterthreadServer() override = default; void ShutdownImpl() override; private: uint16_t _virtualPort; }; auto NetworkServer::StartInterthreadServer(ptr<ServerNetworkSettings> settings, NewConnectionCallback callback) -> unique_ptr<NetworkServer> { FO_STACK_TRACE_ENTRY(); return SafeAlloc::MakeUnique<InterthreadServer>(settings, std::move(callback)); } NetworkServerConnection_Interthread::NetworkServerConnection_Interthread(ptr<ServerNetworkSettings> settings, InterthreadDataCallback send) : NetworkServerConnection(settings), _send {std::move(send)} { FO_STACK_TRACE_ENTRY(); } void NetworkServerConnection_Interthread::Receive(const_span<uint8_t> buf) { FO_STACK_TRACE_ENTRY(); if (!buf.empty()) { ReceiveCallback(buf); } else { { scoped_lock locker {_sendLocker}; _send = nullptr; } Disconnect(); } } void NetworkServerConnection_Interthread::DispatchImpl() { FO_STACK_TRACE_ENTRY(); auto buf = SendCallback(); if (!buf.empty()) { scoped_lock locker {_sendLocker}; if (_send) { _send(buf); } } } void NetworkServerConnection_Interthread::DisconnectImpl() { FO_STACK_TRACE_ENTRY(); scoped_lock locker {_sendLocker}; if (_send) { _send({}); _send = nullptr; } } InterthreadServer::InterthreadServer(ptr<ServerNetworkSettings> settings, NewConnectionCallback callback) : _virtualPort {numeric_cast<uint16_t>(settings->ServerPort)} { FO_STACK_TRACE_ENTRY(); scoped_lock locker {InterthreadListenersLocker}; if (InterthreadListeners.count(_virtualPort) != 0) { throw NetworkServerException("Port is busy", _virtualPort); } auto connection_registry = GetConnectionRegistry(); InterthreadListeners.emplace(_virtualPort, [connection_registry_ = std::move(connection_registry), settings, callback_ = std::move(callback)](InterthreadDataCallback client_send) mutable -> InterthreadDataCallback FO_DEFERRED { auto conn = SafeAlloc::MakeShared<NetworkServerConnection_Interthread>(settings, std::move(client_send)); if (connection_registry_->TrackConnection(conn)) { callback_(conn); } return [conn_ = conn](const_span<uint8_t> buf) mutable FO_DEFERRED { conn_->Receive(buf); }; }); } void InterthreadServer::ShutdownImpl() { FO_STACK_TRACE_ENTRY(); scoped_lock locker {InterthreadListenersLocker}; FO_VERIFY_AND_THROW(InterthreadListeners.count(_virtualPort) != 0, "Interthread server shutdown cannot find the registered virtual port listener", _virtualPort, InterthreadListeners.size()); InterthreadListeners.erase(_virtualPort); } FO_END_NAMESPACE