fix vehicle copy on GetAllCars, TSetOfVehicleData is now vector<>

This commit is contained in:
Lion Kortlepel 2021-03-31 12:12:01 +02:00
parent 7231c69e10
commit 56a02f0215
5 changed files with 50 additions and 26 deletions

View File

@ -14,10 +14,10 @@ class TServer;
class TClient final {
public:
using TSetOfVehicleData = std::unordered_set<TVehicleData>;
using TSetOfVehicleData = std::vector<TVehicleData>;
struct TVehicleDataLockPair {
TSetOfVehicleData& VehicleData;
TSetOfVehicleData* VehicleData;
std::unique_lock<std::mutex> Lock;
};
@ -31,6 +31,7 @@ public:
void SetName(const std::string& Name) { mName = Name; }
void SetRoles(const std::string& Role) { mRole = Role; }
void AddIdentifier(const std::string& ID) { mIdentifiers.insert(ID); };
void EraseVehicle(TVehicleData& VehicleData);
std::string GetCarData(int Ident);
void SetUDPAddr(sockaddr_in Addr) { mUDPAddress = Addr; }
void SetDownSock(SOCKET CSock) { mSocket[1] = CSock; }
@ -67,6 +68,8 @@ public:
int SecondsSinceLastPing();
private:
void InsertVehicle(int ID, const std::string& Data);
TServer& mServer;
bool mIsConnected = false;
bool mIsSynced = false;

View File

@ -6,20 +6,25 @@ class TVehicleData final {
public:
TVehicleData(int ID, std::string Data);
~TVehicleData();
// We cannot delete this, since vector needs to be able to copy when it resizes.
// Deleting this causes some wacky template errors which are hard to decipher,
// and end up making no sense, so let's just leave the copy ctor.
// TVehicleData(const TVehicleData&) = delete;
[[nodiscard]] bool IsInvalid() const { return mID == -1; }
[[nodiscard]] int ID() const { return mID; }
[[nodiscard]] std::string Data() const { return mData; }
void SetData(const std::string& Data) const { mData = Data; }
void SetData(const std::string& Data) { mData = Data; }
bool operator==(const TVehicleData& v) const { return mID == v.mID; }
private:
int mID { -1 };
mutable std::string mData;
std::string mData;
};
// TODO: unused now, remove?
namespace std {
template <>
struct hash<TVehicleData> {

View File

@ -9,12 +9,24 @@ void TClient::DeleteCar(int Ident) {
std::unique_lock lock(mVehicleDataMutex);
for (auto& v : mVehicleData) {
if (v.ID() == Ident) {
mVehicleData.erase(v);
EraseVehicle(v);
break;
}
}
}
void TClient::EraseVehicle(TVehicleData& VehicleData) {
std::unique_lock lock(mVehicleDataMutex);
auto iter = std::find_if(mVehicleData.begin(), mVehicleData.end(), [&](auto& elem) {
return VehicleData.ID() == elem.ID();
});
if (iter != mVehicleData.end()) {
mVehicleData.erase(iter);
} else {
debug("tried to erase a vehicle that doesn't exist!");
}
}
void TClient::ClearCars() {
std::unique_lock lock(mVehicleDataMutex);
mVehicleData.clear();
@ -37,11 +49,11 @@ int TClient::GetOpenCarID() const {
void TClient::AddNewCar(int Ident, const std::string& Data) {
std::unique_lock lock(mVehicleDataMutex);
mVehicleData.emplace(Ident, Data);
mVehicleData.emplace_back(Ident, Data);
}
TClient::TVehicleDataLockPair TClient::GetAllCars() {
return { mVehicleData, std::unique_lock(mVehicleDataMutex) };
return { &mVehicleData, std::unique_lock(mVehicleDataMutex) };
}
std::string TClient::GetCarData(int Ident) {

View File

@ -339,15 +339,15 @@ int lua_GetCars(lua_State* L) {
auto MaybeClient = GetClient(Engine().Server(), ID);
if (MaybeClient && !MaybeClient.value().expired()) {
auto Client = MaybeClient.value().lock();
TClient::TSetOfVehicleData VehicleData;
TClient::TSetOfVehicleData* VehicleData;
{ // Vehicle Data Lock Scope
auto LockedData = Client->GetAllCars();
VehicleData = LockedData.VehicleData;
} // End Vehicle Data Lock Scope
if (VehicleData.empty())
if (VehicleData->empty())
return 0;
lua_newtable(L);
for (const auto& v : VehicleData) {
for (const auto& v : *VehicleData) {
lua_pushinteger(L, v.ID());
lua_pushstring(L, v.Data().substr(3).c_str());
lua_settable(L, -3);

View File

@ -88,7 +88,8 @@ void TNetwork::UDPServerMain() {
ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) {
Client = ClientPtr.lock();
}else return true;
} else
return true;
}
if (Client->GetID() == ID) {
@ -312,7 +313,8 @@ void TNetwork::Authentication(SOCKET TCPSock) {
ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) {
Cl = ClientPtr.lock();
} else return true;
} else
return true;
}
info("Client Iteration: Name -> " + Cl->GetName() + ", Guest -> " + std::to_string(Cl->IsGuest()) + ", Roles -> " + Cl->GetRoles());
if (Cl->GetName() == Client->GetName() && Cl->IsGuest() == Client->IsGuest()) {
@ -355,7 +357,7 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
if (!IsSync) {
if (c.IsSyncing()) {
//std::unique_lock Lock(c.MissedPacketQueueMutex());
if(!Data.empty()) {
if (!Data.empty()) {
if (Data.at(0) == 'O' || Data.at(0) == 'A' || Data.at(0) == 'C' || Data.at(0) == 'E') {
c.EnqueuePacket(Data);
}
@ -364,7 +366,6 @@ bool TNetwork::TCPSend(TClient& c, const std::string& Data, bool IsSync) {
}
}
int32_t Size, Sent;
std::string Send(4, 0);
Size = int32_t(Data.size());
@ -488,8 +489,8 @@ void TNetwork::ClientKick(TClient& c, const std::string& R) {
c.SetStatus(-2);
CloseSocketProper(c.GetTCPSock());
}
void TNetwork::Looper(const std::weak_ptr<TClient>& c){
while(!c.expired()) {
void TNetwork::Looper(const std::weak_ptr<TClient>& c) {
while (!c.expired()) {
auto Client = c.lock();
if (Client->GetStatus() < 0) {
debug("client status < 0, breaking client loop");
@ -521,7 +522,7 @@ void TNetwork::Looper(const std::weak_ptr<TClient>& c){
break;
}
}
}else{
} else {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
@ -535,7 +536,7 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
OnConnect(c);
RegisterThread("(" + std::to_string(c.lock()->GetID()) + ") \"" + c.lock()->GetName() + "\"");
std::thread QueueSync(&TNetwork::Looper, this ,c);
std::thread QueueSync(&TNetwork::Looper, this, c);
while (true) {
if (c.expired())
@ -553,7 +554,8 @@ void TNetwork::TCPClient(const std::weak_ptr<TClient>& c) {
}
TServer::GlobalParser(c, res, mPPSMonitor, *this);
}
if(QueueSync.joinable())QueueSync.join();
if (QueueSync.joinable())
QueueSync.join();
if (!c.expired()) {
auto Client = c.lock();
@ -583,12 +585,12 @@ void TNetwork::OnDisconnect(const std::weak_ptr<TClient>& ClientPtr, bool kicked
TClient& c = *LockedClientPtr;
info(c.GetName() + (" Connection Terminated"));
std::string Packet;
TClient::TSetOfVehicleData VehicleData;
TClient::TSetOfVehicleData* VehicleData;
{ // Vehicle Data Lock Scope
auto LockedData = c.GetAllCars();
VehicleData = LockedData.VehicleData;
} // End Vehicle Data Lock Scope
for (auto& v : VehicleData) {
for (auto& v : *VehicleData) {
Packet = "Od:" + std::to_string(c.GetID()) + "-" + std::to_string(v.ID());
SendToAll(&c, Packet, false, true);
}
@ -836,15 +838,16 @@ bool TNetwork::SyncClient(const std::weak_ptr<TClient>& c) {
ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) {
client = ClientPtr.lock();
} else return true;
} else
return true;
}
TClient::TSetOfVehicleData VehicleData;
TClient::TSetOfVehicleData* VehicleData;
{ // Vehicle Data Lock Scope
auto LockedData = client->GetAllCars();
VehicleData = LockedData.VehicleData;
} // End Vehicle Data Lock Scope
if (client != LockedClient) {
for (auto& v : VehicleData) {
for (auto& v : *VehicleData) {
if (LockedClient->GetStatus() < 0) {
Return = true;
res = false;
@ -877,7 +880,8 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
ReadLock Lock(mServer.GetClientMutex());
if (!ClientPtr.expired()) {
Client = ClientPtr.lock();
}else return true;
} else
return true;
}
if (Self || Client.get() != c) {
if (Client->IsSynced() || Client->IsSyncing()) {
@ -886,7 +890,7 @@ void TNetwork::SendToAll(TClient* c, const std::string& Data, bool Self, bool Re
if (Data.length() > 400) {
std::string CMP(Comp(Data));
Client->EnqueuePacket("ABG:" + CMP);
}else{
} else {
Client->EnqueuePacket(Data);
}
//ret = SendLarge(*Client, Data);