From 9d713f1a2824f03a58923b1f7103630340302857 Mon Sep 17 00:00:00 2001 From: Pieter Dewachter Date: Tue, 31 Aug 2021 18:56:05 +0200 Subject: [PATCH 1/5] Only remove an event if all resources that used addEvent for that event are stopped --- Client/mods/deathmatch/logic/CEvents.cpp | 48 ++++++++++++++++-------- Client/mods/deathmatch/logic/CEvents.h | 8 ++-- Server/mods/deathmatch/logic/CEvents.cpp | 48 ++++++++++++++++-------- Server/mods/deathmatch/logic/CEvents.h | 8 ++-- 4 files changed, 74 insertions(+), 38 deletions(-) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp index a62f39e2e5..90689a1e19 100644 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ b/Client/mods/deathmatch/logic/CEvents.cpp @@ -28,16 +28,27 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL assert(szName); assert(szArguments); - // If it already exists, return - if (Get(szName)) - return false; + // Get the event if it already exists + SEvent* pEvent = Get(szName); - // Create and add the event - SEvent* pEvent = new SEvent; - pEvent->strName = szName; - pEvent->strArguments = szArguments; - pEvent->pLuaMain = pLuaMain; - pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; + if (pEvent) + { + // If bAllowRemoteTrigger has been altered, return + if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) + return false; + + // Add pLuaMain to the set, std::set guarantees unique elements + pEvent->pLuaMainSet.insert(pLuaMain); + } + else + { + // Create and add the event + pEvent = new SEvent; + pEvent->strName = szName; + pEvent->strArguments = szArguments; + pEvent->pLuaMainSet.insert(pLuaMain); + pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; + } m_EventHashMap[szName] = pEvent; @@ -80,14 +91,21 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) while (iter != m_EventHashMap.end()) { SEvent* pEvent = (*iter).second; - // If they match, delete it null it and set the bool - if (pEvent != NULL && pEvent->pLuaMain == pMain) + + // If they match, remove pMain from the set and check for deletion + if (pEvent->pLuaMainSet.find(pMain) != pEvent->pLuaMainSet.end()) { - // Delete the object - delete pEvent; + pEvent->pLuaMainSet.erase(pMain); + + // If no pMain is left, delete it null it and set the bool + if (pEvent->pLuaMainSet.size() == 0) + { + // Delete the object + delete pEvent; - // Remove from list - m_EventHashMap.erase(iter++); + // Remove from list + m_EventHashMap.erase(iter++); + } } else ++iter; diff --git a/Client/mods/deathmatch/logic/CEvents.h b/Client/mods/deathmatch/logic/CEvents.h index e5a5ede8ec..1a970540f0 100644 --- a/Client/mods/deathmatch/logic/CEvents.h +++ b/Client/mods/deathmatch/logic/CEvents.h @@ -16,10 +16,10 @@ struct SEvent { - class CLuaMain* pLuaMain; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::set pLuaMainSet; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index f16e81d72e..ae18e4ad76 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -22,16 +22,27 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL assert(szName); assert(szArguments); - // If it already exists, return - if (Get(szName)) - return false; + // Get the event if it already exists + SEvent* pEvent = Get(szName); - // Create and add the event - SEvent* pEvent = new SEvent; - pEvent->strName = szName; - pEvent->strArguments = szArguments; - pEvent->pLuaMain = pLuaMain; - pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; + if (pEvent) + { + // If bAllowRemoteTrigger has been altered, return + if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) + return false; + + // Add pLuaMain to the set, std::set guarantees unique elements + pEvent->pLuaMainSet.insert(pLuaMain); + } + else + { + // Create and add the event + pEvent = new SEvent; + pEvent->strName = szName; + pEvent->strArguments = szArguments; + pEvent->pLuaMainSet.insert(pLuaMain); + pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; + } m_EventHashMap[szName] = pEvent; @@ -68,14 +79,21 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) while (iter != m_EventHashMap.end()) { SEvent* pEvent = (*iter).second; - // If they match, delete it null it and set the bool - if (pEvent->pLuaMain == pMain) + + // If they match, remove pMain from the set and check for deletion + if (pEvent->pLuaMainSet.find(pMain) != pEvent->pLuaMainSet.end()) { - // Delete the object - delete pEvent; + pEvent->pLuaMainSet.erase(pMain); + + // If no pMain is left, delete it null it and set the bool + if (pEvent->pLuaMainSet.size() == 0) + { + // Delete the object + delete pEvent; - // Remove from list - m_EventHashMap.erase(iter++); + // Remove from list + m_EventHashMap.erase(iter++); + } } else ++iter; diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h index 2de9531f23..3e6c92bb81 100644 --- a/Server/mods/deathmatch/logic/CEvents.h +++ b/Server/mods/deathmatch/logic/CEvents.h @@ -17,10 +17,10 @@ struct SEvent { - class CLuaMain* pLuaMain; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::set pLuaMainSet; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents From 27c425c98f6ef156da0fc746eebad0be4482498d Mon Sep 17 00:00:00 2001 From: Pieter Dewachter Date: Wed, 1 Sep 2021 12:45:25 +0200 Subject: [PATCH 2/5] Resolve potential infinite loop in CEvents::RemoveAllEvents --- Client/mods/deathmatch/logic/CEvents.cpp | 8 ++++---- Server/mods/deathmatch/logic/CEvents.cpp | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp index 90689a1e19..74639ccaf0 100644 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ b/Client/mods/deathmatch/logic/CEvents.cpp @@ -91,7 +91,7 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) while (iter != m_EventHashMap.end()) { SEvent* pEvent = (*iter).second; - + // If they match, remove pMain from the set and check for deletion if (pEvent->pLuaMainSet.find(pMain) != pEvent->pLuaMainSet.end()) { @@ -104,11 +104,11 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) delete pEvent; // Remove from list - m_EventHashMap.erase(iter++); + m_EventHashMap.erase(iter); } } - else - ++iter; + + ++iter; } } diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index ae18e4ad76..922683d48a 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -92,11 +92,11 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) delete pEvent; // Remove from list - m_EventHashMap.erase(iter++); + m_EventHashMap.erase(iter); } } - else - ++iter; + + ++iter; } } From 914a3e08a2376680f820ab2ea9686a70e1a194c0 Mon Sep 17 00:00:00 2001 From: Pieter Dewachter Date: Fri, 3 Sep 2021 20:56:31 +0200 Subject: [PATCH 3/5] Use std::unordered_set instead of std::set for CEvents, use the according empty() method as well --- Client/mods/deathmatch/logic/CEvents.cpp | 4 ++-- Client/mods/deathmatch/logic/CEvents.h | 8 ++++---- Server/mods/deathmatch/logic/CEvents.cpp | 4 ++-- Server/mods/deathmatch/logic/CEvents.h | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp index 74639ccaf0..4e0d54f38c 100644 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ b/Client/mods/deathmatch/logic/CEvents.cpp @@ -37,7 +37,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) return false; - // Add pLuaMain to the set, std::set guarantees unique elements + // Add pLuaMain to the set, std::unordered_set guarantees unique elements pEvent->pLuaMainSet.insert(pLuaMain); } else @@ -98,7 +98,7 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) pEvent->pLuaMainSet.erase(pMain); // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainSet.size() == 0) + if (pEvent->pLuaMainSet.empty()) { // Delete the object delete pEvent; diff --git a/Client/mods/deathmatch/logic/CEvents.h b/Client/mods/deathmatch/logic/CEvents.h index 1a970540f0..c579ca18c2 100644 --- a/Client/mods/deathmatch/logic/CEvents.h +++ b/Client/mods/deathmatch/logic/CEvents.h @@ -16,10 +16,10 @@ struct SEvent { - std::set pLuaMainSet; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::unordered_set pLuaMainSet; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index 922683d48a..0cc0b89f3b 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -31,7 +31,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) return false; - // Add pLuaMain to the set, std::set guarantees unique elements + // Add pLuaMain to the set, std::unordered_set guarantees unique elements pEvent->pLuaMainSet.insert(pLuaMain); } else @@ -86,7 +86,7 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) pEvent->pLuaMainSet.erase(pMain); // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainSet.size() == 0) + if (pEvent->pLuaMainSet.empty()) { // Delete the object delete pEvent; diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h index 3e6c92bb81..a7ea1bde05 100644 --- a/Server/mods/deathmatch/logic/CEvents.h +++ b/Server/mods/deathmatch/logic/CEvents.h @@ -17,10 +17,10 @@ struct SEvent { - std::set pLuaMainSet; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::unordered_set pLuaMainSet; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents From 0c2bdb667b127dbf78122cbb6f2f3d8cb3513ea4 Mon Sep 17 00:00:00 2001 From: Pieter Dewachter Date: Fri, 3 Sep 2021 21:41:49 +0200 Subject: [PATCH 4/5] Use std::vector for CEvents instead of std::unordered_set since there won't be that many resources and memory layout is preferred over raw speed --- Client/mods/deathmatch/logic/CEvents.cpp | 16 +++++++++------- Client/mods/deathmatch/logic/CEvents.h | 8 ++++---- Server/mods/deathmatch/logic/CEvents.cpp | 16 +++++++++------- Server/mods/deathmatch/logic/CEvents.h | 8 ++++---- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp index 4e0d54f38c..f57c53b3e2 100644 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ b/Client/mods/deathmatch/logic/CEvents.cpp @@ -37,8 +37,9 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) return false; - // Add pLuaMain to the set, std::unordered_set guarantees unique elements - pEvent->pLuaMainSet.insert(pLuaMain); + // Add pLuaMain to the vector, in case it's not already there + if (std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pLuaMain) == pEvent->pLuaMainVector.end()) + pEvent->pLuaMainVector.push_back(pLuaMain); } else { @@ -46,7 +47,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL pEvent = new SEvent; pEvent->strName = szName; pEvent->strArguments = szArguments; - pEvent->pLuaMainSet.insert(pLuaMain); + pEvent->pLuaMainVector.push_back(pLuaMain); pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; } @@ -92,13 +93,14 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) { SEvent* pEvent = (*iter).second; - // If they match, remove pMain from the set and check for deletion - if (pEvent->pLuaMainSet.find(pMain) != pEvent->pLuaMainSet.end()) + // If they match, remove pMain from the vector and check for deletion + std::vector::const_iterator pLuaMainIter = std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pMain); + if (pLuaMainIter != pEvent->pLuaMainVector.end()) { - pEvent->pLuaMainSet.erase(pMain); + pEvent->pLuaMainVector.erase(pLuaMainIter); // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainSet.empty()) + if (pEvent->pLuaMainVector.empty()) { // Delete the object delete pEvent; diff --git a/Client/mods/deathmatch/logic/CEvents.h b/Client/mods/deathmatch/logic/CEvents.h index c579ca18c2..23c4cb513a 100644 --- a/Client/mods/deathmatch/logic/CEvents.h +++ b/Client/mods/deathmatch/logic/CEvents.h @@ -16,10 +16,10 @@ struct SEvent { - std::unordered_set pLuaMainSet; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::vector pLuaMainVector; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index 0cc0b89f3b..f526e0b511 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -31,8 +31,9 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL if (pEvent->bAllowRemoteTrigger != bAllowRemoteTrigger) return false; - // Add pLuaMain to the set, std::unordered_set guarantees unique elements - pEvent->pLuaMainSet.insert(pLuaMain); + // Add pLuaMain to the vector, in case it's not already there + if (std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pLuaMain) == pEvent->pLuaMainVector.end()) + pEvent->pLuaMainVector.push_back(pLuaMain); } else { @@ -40,7 +41,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL pEvent = new SEvent; pEvent->strName = szName; pEvent->strArguments = szArguments; - pEvent->pLuaMainSet.insert(pLuaMain); + pEvent->pLuaMainVector.push_back(pLuaMain); pEvent->bAllowRemoteTrigger = bAllowRemoteTrigger; } @@ -80,13 +81,14 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) { SEvent* pEvent = (*iter).second; - // If they match, remove pMain from the set and check for deletion - if (pEvent->pLuaMainSet.find(pMain) != pEvent->pLuaMainSet.end()) + // If they match, remove pMain from the vector and check for deletion + std::vector::const_iterator pLuaMainIter = std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pMain); + if (pLuaMainIter != pEvent->pLuaMainVector.end()) { - pEvent->pLuaMainSet.erase(pMain); + pEvent->pLuaMainVector.erase(pLuaMainIter); // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainSet.empty()) + if (pEvent->pLuaMainVector.empty()) { // Delete the object delete pEvent; diff --git a/Server/mods/deathmatch/logic/CEvents.h b/Server/mods/deathmatch/logic/CEvents.h index a7ea1bde05..4b6f14eea1 100644 --- a/Server/mods/deathmatch/logic/CEvents.h +++ b/Server/mods/deathmatch/logic/CEvents.h @@ -17,10 +17,10 @@ struct SEvent { - std::unordered_set pLuaMainSet; - std::string strName; - std::string strArguments; - bool bAllowRemoteTrigger; + std::vector pLuaMainVector; + std::string strName; + std::string strArguments; + bool bAllowRemoteTrigger; }; class CEvents From 6b2d00deb9fb04fdbf1bbcfea2eeca6301add587 Mon Sep 17 00:00:00 2001 From: Pieter Dewachter Date: Mon, 13 Sep 2021 19:45:20 +0200 Subject: [PATCH 5/5] Simplify usage of std::vector --- Client/mods/deathmatch/logic/CEvents.cpp | 22 ++++++++-------------- Server/mods/deathmatch/logic/CEvents.cpp | 22 ++++++++-------------- 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/Client/mods/deathmatch/logic/CEvents.cpp b/Client/mods/deathmatch/logic/CEvents.cpp index f57c53b3e2..73c8a328b1 100644 --- a/Client/mods/deathmatch/logic/CEvents.cpp +++ b/Client/mods/deathmatch/logic/CEvents.cpp @@ -38,7 +38,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL return false; // Add pLuaMain to the vector, in case it's not already there - if (std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pLuaMain) == pEvent->pLuaMainVector.end()) + if (!ListContains(pEvent->pLuaMainVector, pLuaMain)) pEvent->pLuaMainVector.push_back(pLuaMain); } else @@ -92,22 +92,16 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) while (iter != m_EventHashMap.end()) { SEvent* pEvent = (*iter).second; + ListRemoveFirst(pEvent->pLuaMainVector, pMain); - // If they match, remove pMain from the vector and check for deletion - std::vector::const_iterator pLuaMainIter = std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pMain); - if (pLuaMainIter != pEvent->pLuaMainVector.end()) + // If no pMain is left, delete it null it and set the bool + if (pEvent->pLuaMainVector.empty()) { - pEvent->pLuaMainVector.erase(pLuaMainIter); + // Delete the object + delete pEvent; - // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainVector.empty()) - { - // Delete the object - delete pEvent; - - // Remove from list - m_EventHashMap.erase(iter); - } + // Remove from list + m_EventHashMap.erase(iter); } ++iter; diff --git a/Server/mods/deathmatch/logic/CEvents.cpp b/Server/mods/deathmatch/logic/CEvents.cpp index f526e0b511..6f81e64edd 100644 --- a/Server/mods/deathmatch/logic/CEvents.cpp +++ b/Server/mods/deathmatch/logic/CEvents.cpp @@ -32,7 +32,7 @@ bool CEvents::AddEvent(const char* szName, const char* szArguments, CLuaMain* pL return false; // Add pLuaMain to the vector, in case it's not already there - if (std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pLuaMain) == pEvent->pLuaMainVector.end()) + if (!ListContains(pEvent->pLuaMainVector, pLuaMain)) pEvent->pLuaMainVector.push_back(pLuaMain); } else @@ -80,22 +80,16 @@ void CEvents::RemoveAllEvents(class CLuaMain* pMain) while (iter != m_EventHashMap.end()) { SEvent* pEvent = (*iter).second; + ListRemoveFirst(pEvent->pLuaMainVector, pMain); - // If they match, remove pMain from the vector and check for deletion - std::vector::const_iterator pLuaMainIter = std::find(pEvent->pLuaMainVector.begin(), pEvent->pLuaMainVector.end(), pMain); - if (pLuaMainIter != pEvent->pLuaMainVector.end()) + // If no pMain is left, delete it null it and set the bool + if (pEvent->pLuaMainVector.empty()) { - pEvent->pLuaMainVector.erase(pLuaMainIter); + // Delete the object + delete pEvent; - // If no pMain is left, delete it null it and set the bool - if (pEvent->pLuaMainVector.empty()) - { - // Delete the object - delete pEvent; - - // Remove from list - m_EventHashMap.erase(iter); - } + // Remove from list + m_EventHashMap.erase(iter); } ++iter;