diff options
| author | littleblack111 <littleblack11111@gmail.com> | 2025-06-12 21:03:17 +0800 |
|---|---|---|
| committer | littleblack111 <littleblack11111@gmail.com> | 2025-06-13 20:22:13 +0800 |
| commit | 3ad8cca9f6fecfb4c1f70f0a8c9d4b860f4c2df3 (patch) | |
| tree | 0e8dc3ed30eac7188714726e188a92ccfe2aa715 /src/sessionManager.cpp | |
| parent | e9f9065e4347ed5e99092612dd90fd85b622ad1c (diff) | |
internal!: refactored to smart pointer
Diffstat (limited to 'src/sessionManager.cpp')
| -rw-r--r-- | src/sessionManager.cpp | 98 |
1 files changed, 55 insertions, 43 deletions
diff --git a/src/sessionManager.cpp b/src/sessionManager.cpp index de55480..7ed1a8e 100644 --- a/src/sessionManager.cpp +++ b/src/sessionManager.cpp @@ -13,8 +13,22 @@ void CSessionManager::shutdownSessions() { if (m_vSessions.empty()) return; - for (auto &session : m_vSessions) - kick(&session, false, "Server shutting down"); + for (auto &[thread, session] : m_vSessions) { + if (session) { + session->setDeaf(false); + session->write("Server shutting down"); + if (!session->getName().empty()) + g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->getName()), std::weak_ptr<CSession>(session)); + } + } + + for (auto &[thread, session] : m_vSessions) { + if (thread.joinable()) + thread.detach(); + session.reset(); + } + + m_vSessions.clear(); } CSessionManager::CSessionManager() { @@ -31,17 +45,16 @@ CSessionManager::~CSessionManager() { for (auto &[thread, session] : m_vSessions) { if (thread.joinable()) thread.detach(); - kick(session.get()); + kick(std::weak_ptr<CSession>(session)); } log(SYS, "SessionManager: bye"); } -std::pair<std::jthread, std::shared_ptr<CSession>> *CSessionManager::newSession() { +void CSessionManager::newSession() { std::shared_ptr session = std::make_shared<CSession>(); - const auto instance = &m_vSessions.emplace_back(std::jthread(&CSession::run, session.get()), session); - instance->second->setSelf(instance); - return instance; + auto &instance = m_vSessions.emplace_back(std::jthread([session]() { session->run(); }), session); + instance.second->self = std::weak_ptr<CSession>(instance.second); } void CSessionManager::run() { @@ -49,9 +62,9 @@ void CSessionManager::run() { newSession(); } -void CSessionManager::broadcast(const std::string &msg, std::optional<const CSession *const> self) const { +void CSessionManager::broadcast(const std::string &msg, std::optional<std::weak_ptr<CSession>> self) const { for (const auto &[thread, session] : m_vSessions) - if (!self || (self && session.get() != *self)) + if (!self || (self && session != self->lock())) session->write(msg); g_pIOManager->addCustom({"", msg}); @@ -73,7 +86,7 @@ bool CSessionManager::nameExists(const std::string &name) { if (it != m_vSessions.end()) { if (!it->second->isValid()) { - kick(it->second.get(), true, "Connection lost"); + kick(std::weak_ptr<CSession>(it->second), true, "Connection lost"); return false; } return true; @@ -81,49 +94,48 @@ bool CSessionManager::nameExists(const std::string &name) { return false; } -CSession *CSessionManager::getByName(const std::string &name) const { +std::shared_ptr<CSession> CSessionManager::getByName(const std::string &name) const { auto it = std::ranges::find_if(m_vSessions, [&name](const auto &s) { return s.second->getName() == name; }); - return it != m_vSessions.end() ? it->second.get() : nullptr; + return it != m_vSessions.end() ? it->second : nullptr; } -CSession *CSessionManager::getByIp(const std::string &ip) const { - auto it = std::ranges::find_if(m_vSessions, [&ip](const auto &s) { log(LOG, s.second->m_ip); return s.second->m_ip == ip; }); - return it != m_vSessions.end() ? it->second.get() : nullptr; +std::shared_ptr<CSession> CSessionManager::getByIp(const std::string &ip) const { + auto it = std::ranges::find_if(m_vSessions, [&ip](const auto &s) { log(LOG, s.second->getIp()); return s.second->getIp() == ip; }); + return it != m_vSessions.end() ? it->second : nullptr; } std::vector<std::shared_ptr<CSession>> CSessionManager::getSessions() const { return m_vSessions | std::views::transform([](const auto &s) { return s.second; }) | std::ranges::to<std::vector>(); } -void CSessionManager::kick(CSession *session, const bool kill, const std::string &reason) { - for (auto &_session : m_vSessions) - if (_session.second.get() == session) - kick(&_session, kill, reason); -} - -void CSessionManager::kick(std::pair<std::jthread, std::shared_ptr<CSession>> *session, const bool kill, const std::string &reason) { - auto it = std::ranges::find_if(m_vSessions, [session](const auto &s) { return s.second.get() == session->second.get(); }); - - if (session->second) - // this only exist when the session is registered - // not sure why the second is null, but m_name definately is since it's setted during register - // but we don't need to notify people if the session didn't even "join"/register anyways - g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->second->m_name), session->second.get()); +void CSessionManager::kick(std::weak_ptr<CSession> session_weak, const bool kill, const std::string &reason) { + auto session = session_weak.lock(); + if (!session) + return; - if (it != m_vSessions.end()) { - if (!reason.empty()) { - it->second->setDeaf(false); - it->second->write(reason); + for (auto it = m_vSessions.begin(); it != m_vSessions.end(); ++it) { + if (it->second == session) { + if (session) + // this only exist when the session is registered + // not sure why the second is null, but m_name definately is since it's setted during register + // but we don't need to notify people if the session didn't even "join"/register anyways + g_pSessionManager->broadcast(NFormatter::fmt(NONEWLINE, "{} has left the chat", session->getName()), session_weak); + + if (!reason.empty()) { + session->setDeaf(false); + session->write(reason); + } + const auto native_handle = it->first.native_handle(); + if (it->first.joinable()) + it->first.detach(); // .detach the thread since it's removing itself + it->second.reset(); + m_vSessions.erase(it); + if (kill && native_handle != 0) + // cancel(terminal/kill) the thread if it doesn't exit on its own + // pthread_cancel cuz it's the safest https://stackoverflow.com/a/3438576 + // need a condition because it might crash if the thread is already dead + pthread_cancel(native_handle); + return; } - const auto native_handle = it->first.native_handle(); - if (it->first.joinable()) - it->first.detach(); // .detach the thread since it's removing itself - it->second.reset(); - m_vSessions.erase(it); - if (kill && native_handle != 0) - // cancel(terminal/kill) the thread if it doesn't exit on its own - // pthread_cancel cuz it's the safest https://stackoverflow.com/a/3438576 - // need a condition because it might crash if the thread is already dead - pthread_cancel(native_handle); } } |
