rework ForEachClient to use concepts instead of SFINAE

This commit is contained in:
Lion Kortlepel 2022-11-13 13:35:25 +01:00
parent d7369c3bc5
commit 844b64f5d9
No known key found for this signature in database
GPG Key ID: 4322FF2B4C71259B
3 changed files with 49 additions and 29 deletions

View File

@ -4,9 +4,11 @@
#include "IterationDecision.h" #include "IterationDecision.h"
#include "RWMutex.h" #include "RWMutex.h"
#include "TScopedTimer.h" #include "TScopedTimer.h"
#include <concepts>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <type_traits>
#include <unordered_set> #include <unordered_set>
#include "BoostAliases.h" #include "BoostAliases.h"
@ -15,6 +17,21 @@ class TClient;
class TNetwork; class TNetwork;
class TPPSMonitor; class TPPSMonitor;
// clang-format doesn't know how to deal with concepts
// clang-format off
template <typename FnT>
concept ForEachHandlerWithDecision = requires(FnT Fn, const std::shared_ptr<TClient>& Ptr) {
requires std::invocable<FnT, const std::shared_ptr<TClient>&> ;
{ std::invoke(Fn, Ptr) } -> std::convertible_to<IterationDecision>;
};
template <typename FnT>
concept ForEachHandler = requires(FnT Fn, const std::shared_ptr<TClient>& Ptr) {
requires std::invocable <FnT, const std::shared_ptr<TClient>&> ;
{ std::invoke(Fn, Ptr) } -> std::same_as<void>;
};
// clang-format on
class TServer final { class TServer final {
public: public:
using TClientSet = std::unordered_set<std::shared_ptr<TClient>>; using TClientSet = std::unordered_set<std::shared_ptr<TClient>>;
@ -26,7 +43,31 @@ public:
// in Fn, return true to continue, return false to break // in Fn, return true to continue, return false to break
[[deprecated("use ForEachClient instead")]] void ForEachClientWeak(const std::function<bool(std::weak_ptr<TClient>)>& Fn); [[deprecated("use ForEachClient instead")]] void ForEachClientWeak(const std::function<bool(std::weak_ptr<TClient>)>& Fn);
// in Fn, return Break or Continue // in Fn, return Break or Continue
void ForEachClient(const std::function<IterationDecision(const std::shared_ptr<TClient>&)>& Fn); template <ForEachHandlerWithDecision FnT>
void ForEachClient(FnT Fn) {
decltype(mClients) Clients;
{
ReadLock lock(mClientsMutex);
Clients = mClients;
}
for (auto& Client : Clients) {
IterationDecision Decision = std::invoke(Fn, Client);
if (Decision == IterationDecision::Break) {
break;
}
}
}
template <ForEachHandler FnT>
void ForEachClient(FnT Fn) {
decltype(mClients) Clients;
{
ReadLock lock(mClientsMutex);
Clients = mClients;
}
for (auto& Client : Clients) {
std::invoke(Fn, Client);
}
}
size_t ClientCount() const; size_t ClientCount() const;
static void GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TNetwork& Network); static void GlobalParser(const std::weak_ptr<TClient>& Client, std::vector<uint8_t>&& Packet, TNetwork& Network);

View File

@ -546,27 +546,20 @@ sol::table TLuaEngine::StateThreadData::Lua_GetPlayerIdentifiers(int ID) {
sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() { sol::table TLuaEngine::StateThreadData::Lua_GetPlayers() {
sol::table Result = mStateView.create_table(); sol::table Result = mStateView.create_table();
mEngine->Server().ForEachClientWeak([&](std::weak_ptr<TClient> Client) -> bool { mEngine->Server().ForEachClient([&](const auto& Client) {
if (!Client.expired()) { Result[Client->GetID()] = Client->GetName();
auto locked = Client.lock();
Result[locked->GetID()] = locked->GetName();
}
return true;
}); });
return Result; return Result;
} }
int TLuaEngine::StateThreadData::Lua_GetPlayerIDByName(const std::string& Name) { int TLuaEngine::StateThreadData::Lua_GetPlayerIDByName(const std::string& Name) {
int Id = -1; int Id = -1;
mEngine->mServer->ForEachClientWeak([&Id, &Name](std::weak_ptr<TClient> Client) -> bool { mEngine->mServer->ForEachClient([&Id, &Name](const auto& Client) -> IterationDecision {
if (!Client.expired()) { if (Client->GetName() == Name) {
auto locked = Client.lock(); Id = Client->GetID();
if (locked->GetName() == Name) { return Break;
Id = locked->GetID();
return false;
}
} }
return true; return Continue;
}); });
return Id; return Id;
} }

View File

@ -203,20 +203,6 @@ void TServer::ForEachClientWeak(const std::function<bool(std::weak_ptr<TClient>)
} }
} }
void TServer::ForEachClient(const std::function<IterationDecision(const std::shared_ptr<TClient>&)>& 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 { size_t TServer::ClientCount() const {
ReadLock Lock(mClientsMutex); ReadLock Lock(mClientsMutex);
return mClients.size(); return mClients.size();