mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-04 00:36:14 +00:00
rework ForEachClient to use concepts instead of SFINAE
This commit is contained in:
parent
d7369c3bc5
commit
844b64f5d9
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user