diff --git a/include/IterationDecision.h b/include/IterationDecision.h new file mode 100644 index 0000000..a692566 --- /dev/null +++ b/include/IterationDecision.h @@ -0,0 +1,6 @@ +#pragma once + +enum IterationDecision { + Continue, + Break, +}; diff --git a/include/TServer.h b/include/TServer.h index a63fd9e..59b7109 100644 --- a/include/TServer.h +++ b/include/TServer.h @@ -1,6 +1,7 @@ #pragma once #include "IThreaded.h" +#include "IterationDecision.h" #include "RWMutex.h" #include "TScopedTimer.h" #include @@ -23,7 +24,9 @@ public: void InsertClient(const std::shared_ptr& Ptr); void RemoveClient(const std::weak_ptr&); // in Fn, return true to continue, return false to break - void ForEachClient(const std::function)>& Fn); + [[deprecated("use ForEachClient instead")]] void ForEachClientWeak(const std::function)>& Fn); + // in Fn, return Break or Continue + void ForEachClient(const std::function&)>& Fn); size_t ClientCount() const; static void GlobalParser(const std::weak_ptr& Client, std::vector&& Packet, TNetwork& Network); diff --git a/src/Client.cpp b/src/Client.cpp index 8a107a7..a00b35d 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -138,7 +138,7 @@ int TClient::SecondsSinceLastPing() { std::optional> GetClient(TServer& Server, int ID) { std::optional> MaybeClient { std::nullopt }; - Server.ForEachClient([&](std::weak_ptr CPtr) -> bool { + Server.ForEachClientWeak([&](std::weak_ptr CPtr) -> bool { ReadLock Lock(Server.GetClientMutex()); try { auto C = CPtr.lock(); diff --git a/src/TConsole.cpp b/src/TConsole.cpp index a11af1f..caaefb6 100644 --- a/src/TConsole.cpp +++ b/src/TConsole.cpp @@ -298,7 +298,7 @@ void TConsole::Command_Debug(const std::string&, const std::vector& connection and do not necessarily reflect the *current* data rate of that client. )")); - mLuaEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { if (!Client.expired()) { auto Locked = Client.lock(); std::string State = ""; @@ -390,7 +390,7 @@ void TConsole::Command_Kick(const std::string&, const std::vector& beammp_trace("attempt to kick '" + Name + "' for '" + Reason + "'"); bool Kicked = false; - mLuaEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { auto Locked = Client.lock(); if (Locked) { if (StringStartsWithLower(Locked->GetName(), Name)) { @@ -552,7 +552,7 @@ void TConsole::Command_List(const std::string&, const std::vector& } else { std::stringstream ss; ss << std::left << std::setw(25) << "Name" << std::setw(6) << "ID" << std::setw(6) << "Cars" << std::endl; - mLuaEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { if (!Client.expired()) { auto locked = Client.lock(); ss << std::left << std::setw(25) << locked->GetName() @@ -579,7 +579,7 @@ void TConsole::Command_Status(const std::string&, const std::vector size_t SyncingCount = 0; size_t MissedPacketQueueSum = 0; int LargestSecondsSinceLastPing = 0; - mLuaEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { if (!Client.expired()) { auto Locked = Client.lock(); CarCount += Locked->GetCarCount(); @@ -680,7 +680,7 @@ void TConsole::Autocomplete_Lua(const std::string& stub, std::vector& suggestions) { std::string stub_lower = boost::algorithm::to_lower_copy(stub); - mLuaEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mLuaEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { auto Locked = Client.lock(); if (Locked) { if (StringStartsWithLower(Locked->GetName(), stub_lower)) { diff --git a/src/THeartbeatThread.cpp b/src/THeartbeatThread.cpp index f7aaecc..8672120 100644 --- a/src/THeartbeatThread.cpp +++ b/src/THeartbeatThread.cpp @@ -167,7 +167,7 @@ THeartbeatThread::THeartbeatThread(TResourceManager& ResourceManager, TServer& S } std::string THeartbeatThread::GetPlayers() { std::string Return; - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { Return += ClientPtr.lock()->GetName() + ";"; diff --git a/src/TLuaEngine.cpp b/src/TLuaEngine.cpp index 6881236..610b699 100644 --- a/src/TLuaEngine.cpp +++ b/src/TLuaEngine.cpp @@ -546,7 +546,7 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) { sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() { sol::table Result = mStateView.create_table(); - mEngine->Server().ForEachClient([&](std::weak_ptr Client) -> bool { + mEngine->Server().ForEachClientWeak([&](std::weak_ptr Client) -> bool { if (!Client.expired()) { auto locked = Client.lock(); Result[locked->GetID()] = locked->GetName(); @@ -558,7 +558,7 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() { int TLuaEngine::StateThreadData::Lua_GetPlayerIDByName(const std::string& Name) { int Id = -1; - mEngine->mServer->ForEachClient([&Id, &Name](std::weak_ptr Client) -> bool { + mEngine->mServer->ForEachClientWeak([&Id, &Name](std::weak_ptr Client) -> bool { if (!Client.expired()) { auto locked = Client.lock(); if (locked->GetName() == Name) { diff --git a/src/TNetwork.cpp b/src/TNetwork.cpp index ce320d9..8f036a7 100644 --- a/src/TNetwork.cpp +++ b/src/TNetwork.cpp @@ -52,7 +52,7 @@ TNetwork::TNetwork(TServer& Server, TPPSMonitor& PPSMonitor, TResourceManager& R auto Futures = LuaAPI::MP::Engine->TriggerEvent("onShutdown", ""); TLuaEngine::WaitForAll(Futures, std::chrono::seconds(60)); beammp_debug("Kicking all players due to shutdown"); - Server.ForEachClient([&](std::weak_ptr client) -> bool { + Server.ForEachClientWeak([&](std::weak_ptr client) -> bool { if (!client.expired()) { ClientKick(*client.lock(), "Server shutdown"); } @@ -213,7 +213,7 @@ void TNetwork::HandleDownload(TConnection&& Conn) { return; } auto ID = uint8_t(D); - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { auto c = ClientPtr.lock(); @@ -298,7 +298,7 @@ std::shared_ptr TNetwork::Authentication(TConnection&& RawConnection) { } beammp_debug("Name -> " + Client->GetName() + ", Guest -> " + std::to_string(Client->IsGuest()) + ", Roles -> " + Client->GetRoles()); - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { std::shared_ptr Cl; { ReadLock Lock(mServer.GetClientMutex()); @@ -534,7 +534,7 @@ void TNetwork::TCPClient(const std::weak_ptr& c) { void TNetwork::UpdatePlayer(TClient& Client) { std::string Packet = ("Ss") + std::to_string(mServer.ClientCount()) + "/" + std::to_string(Application::GetSettingInt(StrMaxPlayers)) + ":"; - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { auto c = ClientPtr.lock(); @@ -582,7 +582,7 @@ int TNetwork::OpenID() { bool found; do { found = true; - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { ReadLock Lock(mServer.GetClientMutex()); if (!ClientPtr.expired()) { auto c = ClientPtr.lock(); @@ -852,7 +852,7 @@ bool TNetwork::SyncClient(const std::weak_ptr& c) { LockedClient->SetIsSyncing(true); bool Return = false; bool res = true; - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { std::shared_ptr client; { ReadLock Lock(mServer.GetClientMutex()); @@ -893,7 +893,7 @@ void TNetwork::SendToAll(TClient* c, const std::vector& Data, bool Self beammp_assert(c); char C = Data.at(0); bool ret = true; - mServer.ForEachClient([&](std::weak_ptr ClientPtr) -> bool { + mServer.ForEachClientWeak([&](std::weak_ptr ClientPtr) -> bool { std::shared_ptr Client; try { ReadLock Lock(mServer.GetClientMutex()); diff --git a/src/TPPSMonitor.cpp b/src/TPPSMonitor.cpp index 3edd17d..3bc3902 100644 --- a/src/TPPSMonitor.cpp +++ b/src/TPPSMonitor.cpp @@ -33,7 +33,7 @@ void TPPSMonitor::operator()() { Application::SetPPS("-"); continue; } - mServer.ForEachClient([&](const std::weak_ptr& ClientPtr) -> bool { + mServer.ForEachClientWeak([&](const std::weak_ptr& ClientPtr) -> bool { std::shared_ptr c; { ReadLock Lock(mServer.GetClientMutex()); diff --git a/src/TServer.cpp b/src/TServer.cpp index 5473e5e..96f80a3 100644 --- a/src/TServer.cpp +++ b/src/TServer.cpp @@ -2,6 +2,7 @@ #include "Client.h" #include "Common.h" #include "CustomAssert.h" +#include "IterationDecision.h" #include "TNetwork.h" #include "TPPSMonitor.h" #include @@ -189,7 +190,7 @@ void TServer::RemoveClient(const std::weak_ptr& WeakClientPtr) { mClients.erase(WeakClientPtr.lock()); } -void TServer::ForEachClient(const std::function)>& Fn) { +void TServer::ForEachClientWeak(const std::function)>& Fn) { decltype(mClients) Clients; { ReadLock lock(mClientsMutex); @@ -202,6 +203,20 @@ void TServer::ForEachClient(const std::function)>& F } } +void TServer::ForEachClient(const std::function&)>& Fn) { + decltype(mClients) Clients; + { + ReadLock lock(mClientsMutex); + Clients = mClients; + } + for (auto& Client : Clients) { + auto Decision = Fn(Client); + if (Decision == IterationDecision::Break) { + break; + } + } +} + size_t TServer::ClientCount() const { ReadLock Lock(mClientsMutex); return mClients.size();