diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-06-19 18:45:34 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-06-19 18:45:34 +0800 |
| commit | cad2569f10e6c0131e5e645ee76330c776b91547 (patch) | |
| tree | f246b6a9799644c735228c6c5df2ece65e0d028d | |
| parent | b3a3e73aaefa39e052e53f9f42c6d0e2f7e1bb9b (diff) | |
fix!: share pointer
for details: https://stackoverflow.com/a/5548314
| -rw-r--r-- | include/libsock/server/client.hpp | 10 | ||||
| -rw-r--r-- | include/libsock/server/clients.hpp | 11 | ||||
| -rw-r--r-- | include/libsock/server/server.hpp | 9 | ||||
| -rw-r--r-- | src/server/client.cpp | 17 | ||||
| -rw-r--r-- | src/server/clients.cpp | 27 | ||||
| -rw-r--r-- | src/server/server.cpp | 29 |
6 files changed, 74 insertions, 29 deletions
diff --git a/include/libsock/server/client.hpp b/include/libsock/server/client.hpp index 1799f34..0579a38 100644 --- a/include/libsock/server/client.hpp +++ b/include/libsock/server/client.hpp @@ -1,6 +1,8 @@ #pragma once #include "../types.hpp" +#include "clients.hpp" +#include "server.hpp" #include <any> #include <format> #include <functional> @@ -12,12 +14,6 @@ namespace LibSock { namespace Server { -class Server; -class Clients; - -extern SP<Server> pServer; -extern SP<Clients> pClients; - struct SRecvData { std::string data; const size_t size = 1024; @@ -52,7 +48,7 @@ class Client { bool isValid(); private: - Client(SP<Server> server = SP<Server>(pServer), SP<Clients> clients = pClients, bool track = false, bool oneShot = true); + Client(SP<Server> server = pServer, SP<Clients> clients = pClients, bool track = false, bool oneShot = true); WP<Client> self; SP<LibSock::CFileDescriptor> m_sockfd; diff --git a/include/libsock/server/clients.hpp b/include/libsock/server/clients.hpp index ba0b40d..8eccbb7 100644 --- a/include/libsock/server/clients.hpp +++ b/include/libsock/server/clients.hpp @@ -3,6 +3,7 @@ #include "../types.hpp" #include <any> #include <functional> +#include <memory> #include <optional> #include <string> #include <thread> @@ -17,9 +18,10 @@ struct SData { std::string msg; std::optional<WP<Client>> sender = std::nullopt; }; -class Clients { + +class Clients : public std::enable_shared_from_this<Clients> { public: - Clients(); + static SP<Clients> create(); ~Clients(); WP<Client> newClient(std::optional<std::function<std::any(WP<Client>)>> cb = std::nullopt); @@ -36,13 +38,16 @@ class Clients { std::vector<SData> getDatas() const; private: + Clients(); void broadcast(const SData &msg); std::vector<std::pair<std::jthread, SP<Client>>> m_vClients; std::vector<SData> m_vDatas; + SP<Clients> get(); + friend class Client; }; - +inline SP<Clients> pClients; } // namespace Server } // namespace LibSock diff --git a/include/libsock/server/server.hpp b/include/libsock/server/server.hpp index 1b52e2f..225bdb0 100644 --- a/include/libsock/server/server.hpp +++ b/include/libsock/server/server.hpp @@ -1,24 +1,27 @@ #pragma once #include "../types.hpp" +#include <memory> #include <mutex> #include <netinet/in.h> -#include <vector> namespace LibSock { namespace Server { -class Server { +class Server : public std::enable_shared_from_this<Server> { public: - Server(uint16_t port, bool reuseaddr = true, bool keepalive = false); + static SP<Server> create(uint16_t port, bool reuseaddr = true, bool keepalive = false); ~Server(); SP<LibSock::CFileDescriptor> getSocket() const; private: + Server(uint16_t port, bool reuseaddr = true, bool keepalive = false); SP<LibSock::CFileDescriptor> m_sockfd; sockaddr_in m_addr; uint16_t m_port; + SP<Server> get(); + mutable std::mutex m_mutex; }; inline SP<Server> pServer; diff --git a/src/server/client.cpp b/src/server/client.cpp index cfc512a..01e4544 100644 --- a/src/server/client.cpp +++ b/src/server/client.cpp @@ -16,13 +16,16 @@ using namespace LibSock::Server; Client::Client(SP<Server> server, SP<Clients> clients, bool track, bool oneShot) : m_track(track) , m_oneShot(oneShot) { - if (!pServer || !pClients) - throw std::runtime_error("server:client: Server/ClientManager doesn't exist"); - m_sockfd = std::make_shared<LibSock::CFileDescriptor>( - accept(pServer->getSocket()->get(), reinterpret_cast<sockaddr *>(&m_addr), - &m_addrLen) - ); // if this is in the init list, it will run before - // m_addrLen, so it won't work :/ + pServer = std::move(server); + pClients = std::move(clients); + + if (!pClients) + throw std::runtime_error("server:client: ClientManager doesn't exist"); + if (!pServer) + throw std::runtime_error("server:client: Server doesn't exist"); + + m_sockfd = std::make_shared<LibSock::CFileDescriptor>(accept(pServer->getSocket()->get(), reinterpret_cast<sockaddr *>(&m_addr), &m_addrLen)); // if this is in the init list, it will run before + // m_addrLen, so it won't work :/ if (!m_sockfd->isValid()) throw std::runtime_error("server:client: Failed to create socket"); diff --git a/src/server/clients.cpp b/src/server/clients.cpp index c957d92..201ccc6 100644 --- a/src/server/clients.cpp +++ b/src/server/clients.cpp @@ -9,6 +9,9 @@ using namespace LibSock::Server; +namespace LibSock { +namespace Server { + void Clients::shutdownClients(std::optional<std::function<std::any(const std::vector<std::pair<std::jthread, SP<Client>>> &)>> cb) { if (m_vClients.empty()) return; @@ -27,14 +30,25 @@ void Clients::shutdownClients(std::optional<std::function<std::any(const std::ve Clients::Clients() { if (std::atexit([]() { - pClients->shutdownClients(); + if (pClients) + pClients->shutdownClients(); })) void(); // failed to register exit handler... +} + +SP<Clients> Clients::create() { if (pClients) - throw std::runtime_error("server:client: ClientManager already exist"); + throw std::runtime_error("server:clients ClientManager already exist"); - pClients = SP<Clients>(this); -}; + pClients = SP<Clients>(new Clients()); + return pClients; +} + +SP<Clients> Clients::get() { + if (!pClients) + pClients = shared_from_this(); + return pClients; +} Clients::~Clients() { for (auto &[thread, client] : m_vClients) { @@ -45,7 +59,7 @@ Clients::~Clients() { } WP<Client> Clients::newClient(std::optional<std::function<std::any(WP<Client>)>> cb) { - SP client = SP<Client>(new Client()); + SP client = SP<Client>(new Client(pServer, shared_from_this())); auto &instance = m_vClients.emplace_back(std::jthread([client]() { client->run(); }), client); instance.second->self = std::weak_ptr<Client>(instance.second); if (cb) @@ -111,3 +125,6 @@ void Clients::kick(WP<Client> clientWeak, const bool kill, const std::string &re } } } + +} // namespace Server +} // namespace LibSock diff --git a/src/server/server.cpp b/src/server/server.cpp index 5f10ac6..63ada20 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -8,6 +8,9 @@ using namespace LibSock::Server; +namespace LibSock { +namespace Server { + Server::Server(uint16_t port, bool reuseaddr, bool keepalive) : m_sockfd( std::make_shared<LibSock::CFileDescriptor>(socket(AF_INET, SOCK_STREAM, 0)) @@ -36,10 +39,28 @@ Server::Server(uint16_t port, bool reuseaddr, bool keepalive) if (bind(m_sockfd->get(), reinterpret_cast<sockaddr *>(&m_addr), sizeof(m_addr)) || listen(m_sockfd->get(), 5)) throw std::runtime_error("server:server Failed to bind or listen on socket"); +} + +SP<Server> Server::create(uint16_t port, bool reuseaddr, bool keepalive) { + if (pServer) + throw std::runtime_error("server:server Server already exist"); + pServer = SP<Server>(new Server(port, reuseaddr, keepalive)); + return pServer; +} + +SP<Server> Server::get() { + if (!pServer) + pServer = shared_from_this(); + return pServer; +} - pServer = SP<Server>(this); -}; +Server::~Server() { + m_sockfd.reset(); +} -Server::~Server() { m_sockfd.reset(); } +SP<LibSock::CFileDescriptor> Server::getSocket() const { + return m_sockfd; +} -std::shared_ptr<LibSock::CFileDescriptor> Server::getSocket() const { return m_sockfd; } +} // namespace Server +} // namespace LibSock |
