diff --git a/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt b/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt index 082a91842c..65c510611b 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt +++ b/Sources/Plasma/NucleusLib/pnUtils/CMakeLists.txt @@ -4,7 +4,6 @@ set(pnUtils_HEADERS pnUtCoreLib.h pnUtAllIncludes.h pnUtCrypt.h - pnUtHash.h pnUtList.h pnUtStr.h pnUtTime.h @@ -12,7 +11,6 @@ set(pnUtils_HEADERS set(pnUtils_SOURCES pnUtCrypt.cpp - pnUtHash.cpp pnUtList.cpp pnUtStr.cpp pnUtTime.cpp diff --git a/Sources/Plasma/NucleusLib/pnUtils/pnUtAllIncludes.h b/Sources/Plasma/NucleusLib/pnUtils/pnUtAllIncludes.h index a5afd7e99d..9fdffb9c68 100644 --- a/Sources/Plasma/NucleusLib/pnUtils/pnUtAllIncludes.h +++ b/Sources/Plasma/NucleusLib/pnUtils/pnUtAllIncludes.h @@ -51,7 +51,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnUtCoreLib.h" // must be first in list #include "pnUtList.h" -#include "pnUtHash.h" #include "pnUtTime.h" #include "pnUtStr.h" #include "pnUtCrypt.h" diff --git a/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.cpp b/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.cpp deleted file mode 100644 index 9b5e63696a..0000000000 --- a/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*==LICENSE==* - -CyanWorlds.com Engine - MMOG client, server and tools -Copyright (C) 2011 Cyan Worlds, Inc. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Additional permissions under GNU GPL version 3 section 7 - -If you modify this Program, or any covered work, by linking or -combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, -NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent -JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK -(or a modified version of those libraries), -containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, -PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG -JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the -licensors of this Program grant you additional -permission to convey the resulting work. Corresponding Source for a -non-source form of such a combination shall include the source code for -the parts of OpenSSL and IJG JPEG Library used as well as that of the covered -work. - -You can contact Cyan Worlds, Inc. by email legal@cyan.com - or by snail mail at: - Cyan Worlds, Inc. - 14617 N Newport Hwy - Mead, WA 99021 - -*==LICENSE==*/ -/***************************************************************************** -* -* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtHash.cpp -* -***/ - -#include "Pch.h" -#include "pnUtHash.h" - -/**************************************************************************** -* -* CHashValue -* -***/ - -// These random values were generated by the radioactive decay based -// random number generator at www.fourmilab.ch -const uint32_t CHashValue::s_hashTable[] = { - 0xe8fd2035, 0xaf1add63, 0x049fb872, 0xcf9bb8eb, 0xc30d2a72, 0x15efaec1, 0xd250c7d9, 0xaf3c60a8, - 0x17ae32ff, 0x4089cd9e, 0x91dd6936, 0x093f880d, 0x9608ae8f, 0x452c0e11, 0xb6840ffd, 0x3e36c913, - 0x393114fd, 0xa72556b2, 0x7c338fb7, 0x4e445027, 0x2864eace, 0x9b0a17d6, 0x108da74b, 0xf2c479c1, - 0x288a43ac, 0x241e8411, 0x12ace782, 0xfb015799, 0x8b4dd597, 0x97199bc0, 0x621f0cce, 0x1658553e, - 0x99697839, 0xe3efb551, 0xbc1a2625, 0x54583c22, 0x9693d685, 0x612f910a, 0x080ccee8, 0xd00a43c9, - 0x86e6984d, 0x793245cf, 0x5335afa0, 0xdb8734d8, 0xfe5ab506, 0x3aae2ec1, 0x0aac22a3, 0xf3cd2c16, - 0x3d3039d1, 0x070b576d, 0x3a624bff, 0x0e185383, 0x78316efa, 0xafbef9ad, 0x556130cc, 0x54813111, - 0xc0e59be8, 0x30010241, 0x2cfa9040, 0x5a039832, 0x68a8a31d, 0xac786303, 0xe81b7dea, 0x2e3d7f5a, - 0xabb30a5c, 0xab08fef0, 0xf88cdc9d, 0x962d8361, 0x82ae270c, 0xc45a6e9c, 0x506a3f62, 0xed7c8f10, - 0x64631545, 0xea26488a, 0xd39f06f7, 0xafa35b6b, 0xdd1f83fb, 0x60b57a99, 0x636373ee, 0x05e82732, - 0xb2eaf275, 0x4763208c, 0x49499166, 0x8e436c6a, 0x3a4f831a, 0x57b7c11e, 0xbd751298, 0x6217ffbc, - 0x789efe70, 0x91d695cc, 0xa7e9049e, 0x12b74cdb, 0x40a2d8e6, 0x4dd33013, 0x506ec265, 0x81b2a421, - 0xdf98bac4, 0x554e33d0, 0x514decf9, 0x4374274c, 0x70b09e64, 0xac951473, 0xd6bb35eb, 0xa65ed4cf, - 0x71f724ac, 0x91e8da43, 0xe386dcee, 0x45bc6b20, 0x08ddf47a, 0xadac9571, 0x44d3cddf, 0x535ace85, - 0x5ac801cc, 0x89e90941, 0xa0507200, 0xe4b2a9b2, 0x00922b39, 0x2848f374, 0xfbe97b80, 0x77ea2e00, - 0x05eea617, 0x2bf0baf7, 0x0c97f929, 0x4d3190c0, 0x31f58de0, 0x7cae5dc4, 0x39f33590, 0x9cd39b3f, - 0x98b0bf46, 0x393169f1, 0x9f8271da, 0x0b85462f, 0xb8b81857, 0xed66ce2c, 0x6f97f3bb, 0x87e8c7dd, - 0x55741d88, 0x9ccd43b8, 0xe537d98a, 0x64a28550, 0x165ba5bf, 0xe4229568, 0x1af7c624, 0x059b9f7a, - 0x38129d4a, 0x73dca9ba, 0xe0185118, 0x48560fdb, 0xb7d0ec6b, 0x1acd6d4b, 0x84ab7a10, 0xcd9bf830, - 0x539d6be2, 0xfdcb65f4, 0x183a4dd7, 0xc4425aa4, 0xa3934d5f, 0xf71b8023, 0x30c109f7, 0x512e5128, - 0x7decdea5, 0xd3aded88, 0x34288710, 0x0c07a16e, 0xec0299da, 0x1e738f1b, 0xd7b898e1, 0x1b7318fd, - 0x3b67392d, 0x60da77b3, 0x614d4804, 0xb854468a, 0x4dbfc9fd, 0x85185833, 0x56095260, 0xb85d0771, - 0xbfe579e7, 0x51ca011b, 0xcebd2983, 0x4d56cda1, 0x5ec08b9a, 0x6bf9aa6f, 0x7da1e2c0, 0x4499dd84, - 0x95ca5ba3, 0xd0f9e77b, 0x5d099253, 0xbe943272, 0x1a87fe96, 0x29584d77, 0x0344f269, 0x2bdafede, - 0x4ababc94, 0x7a06acb7, 0x0a4c1efe, 0x8699f00f, 0x0f74e313, 0x0469ac17, 0x80f17875, 0xa6aecf16, - 0x0d772a15, 0x60eb0850, 0xa852be33, 0xe1574793, 0x7847204c, 0x1cea62ac, 0xb5948e41, 0x0e574ae9, - 0xdeb24de3, 0xe6472a0b, 0xaaaaf355, 0xa271aeae, 0xf3d5d209, 0x4f8fa676, 0x25ff71c9, 0x3f38d7df, - 0x0a8cd458, 0x5c6ad602, 0x06d0c0ec, 0x0d84ac0f, 0xf3cc4a59, 0xd6f04d8c, 0x1b3c3229, 0xc8281f6d, - 0x9410dd7c, 0x502519d1, 0x4449a76a, 0x88ba67b6, 0x8f710894, 0x7b63230e, 0xc095db28, 0x155a4ac7, - 0x0d418a5d, 0xe2b69e59, 0xeab4ac50, 0x0de06aae, 0x60f272fa, 0x408aefd8, 0x01c3435a, 0x0880c1e3, - 0x4f23137b, 0x9dfd6434, 0xd1e25d94, 0xbad4c88a, 0x0746edf9, 0x8103a9aa, 0xc8c73617, 0xe0f2759a, - 0x00161c79, 0xd4545360, 0x1763cc5b, 0x296361fa, 0xbc35858d, 0xdaed5e93, 0x0b9d0aed, 0x01c45a64, -}; - diff --git a/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.h b/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.h deleted file mode 100644 index 0bbf04dcaf..0000000000 --- a/Sources/Plasma/NucleusLib/pnUtils/pnUtHash.h +++ /dev/null @@ -1,610 +0,0 @@ -/*==LICENSE==* - -CyanWorlds.com Engine - MMOG client, server and tools -Copyright (C) 2011 Cyan Worlds, Inc. - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . - -Additional permissions under GNU GPL version 3 section 7 - -If you modify this Program, or any covered work, by linking or -combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, -NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent -JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK -(or a modified version of those libraries), -containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, -PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG -JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the -licensors of this Program grant you additional -permission to convey the resulting work. Corresponding Source for a -non-source form of such a combination shall include the source code for -the parts of OpenSSL and IJG JPEG Library used as well as that of the covered -work. - -You can contact Cyan Worlds, Inc. by email legal@cyan.com - or by snail mail at: - Cyan Worlds, Inc. - 14617 N Newport Hwy - Mead, WA 99021 - -*==LICENSE==*/ -/***************************************************************************** -* -* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtHash.h -* -***/ - -#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTHASH_H -#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTHASH_H - -#include "pnUtList.h" -#include "pnUtStr.h" - -/**************************************************************************** -* -* Macros -* -***/ - -// Define a field inside an object that is used to link it into a hash table -#define HASHLINK(object) THashLink< object > - -// Define a hash table: -// - starts with kSlotMinCount rows -// - can grow to kDefaultSlotMaxCount rows -// (hash table grows when a row contains more than kGrowOnListSize entries -#define HASHTABLEDECL(object,key,link) THashTableDecl< object, key, offsetof(object,link), 0 > - - -#if defined(_MSC_VER) -#define forceinline __forceinline -#else -#define forceinline inline -#endif - - -/**************************************************************************** -* -* Forward declarations -* -***/ - -template -class THashLink; - -template -class TBaseHashTable; - - -/**************************************************************************** -* -* CHashValue -* -***/ - -class CHashValue { -private: - static const uint32_t s_hashTable[]; - - uint32_t m_result; - - inline void Construct () { m_result = 0x325d1eae; } - -public: - static uint32_t LookupHashBits (unsigned value) { ASSERT(value < 0x100); return s_hashTable[value]; } - - inline CHashValue () { Construct() ; } - inline CHashValue (const CHashValue & source) { m_result = source.m_result; } - inline CHashValue (const void * data, unsigned bytes) { Construct(); Hash(data, bytes); } - inline CHashValue & operator= (const CHashValue & source) { m_result = source.m_result; return *this; } - inline bool operator== (const CHashValue & source) const { return (m_result == source.m_result); } - - inline uint32_t GetHash () const { return m_result; } - - forceinline void Hash (const void * data, unsigned bytes); - forceinline void Hash8 (unsigned data); - forceinline void Hash16 (unsigned data); - forceinline void Hash32 (unsigned data); - -}; - -//=========================================================================== -void CHashValue::Hash (const void * data, unsigned bytes) { - for (const uint8_t * curr = (const uint8_t *)data, * term = curr + bytes; curr != term; ++curr) - Hash8(*curr); -} - -//=========================================================================== -void CHashValue::Hash8 (unsigned data) { - m_result += s_hashTable[m_result >> 24] ^ (m_result >> 6) ^ s_hashTable[data & 0xff]; -} - -//=========================================================================== -void CHashValue::Hash16 (unsigned data) { - Hash8(data); - Hash8(data >> 8); -} - -//=========================================================================== -void CHashValue::Hash32 (unsigned data) { - Hash8(data); - Hash8(data >> 8); - Hash8(data >> 16); - Hash8(data >> 24); -} - - -/**************************************************************************** -* -* THashLink -* -***/ - -template -class THashLink { - friend class TBaseHashTable; - -private: - unsigned m_hash; - LINK(T) m_linkToFull; - LINK(T) m_linkToSlot; - -public: - THashLink() : m_hash(0) { } - - inline bool IsLinked () const; - inline T * Next (); - inline const T * Next () const; - inline T * Prev (); - inline const T * Prev () const; - inline void Unlink (); -}; - -//=========================================================================== -template -bool THashLink::IsLinked () const { - return m_linkToFull.IsLinked(); -} - -//=========================================================================== -template -T * THashLink::Next () { - return m_linkToFull.Next(); -} - -//=========================================================================== -template -const T * THashLink::Next () const { - return m_linkToFull.Next(); -} - -//=========================================================================== -template -T * THashLink::Prev () { - return m_linkToFull.Prev(); -} - -//=========================================================================== -template -const T * THashLink::Prev () const { - return m_linkToFull.Prev(); -} - -//=========================================================================== -template -void THashLink::Unlink () { - m_linkToFull.Unlink(); - m_linkToSlot.Unlink(); -} - - -/**************************************************************************** -* -* TBaseHashTable -* -***/ - -template -class TBaseHashTable { - -private: - enum { kSlotMinCount = 8 }; - enum { kDefaultSlotMaxCount = 1024 }; - enum { kGrowOnListSize = 5 }; - - LIST(T) m_fullList; - int m_linkOffset; - std::vector m_slotListArray; - unsigned m_slotMask; // always set to a power of two minus one - unsigned m_slotMaxCount; - - inline bool CheckGrowTable (LIST(T) * slotList); - inline const THashLink & GetLink (const T * object) const; - inline THashLink & GetLink (T * object); - inline void SetSlotCount (unsigned count); - -protected: - inline unsigned GetHash (const T * object) const; - inline unsigned & GetHash (T * object); - inline const LIST(T) & GetSlotList (unsigned hash) const; - inline LIST(T) & GetSlotList (unsigned hash); - inline void SetLinkOffset (int linkOffset, unsigned maxSize); - inline void SetSlotMaxCount (unsigned count); - -public: - inline TBaseHashTable (); - inline TBaseHashTable (const TBaseHashTable & source); - inline TBaseHashTable & operator= (const TBaseHashTable & source); - - inline void Add (T * object, unsigned hash); - inline void Clear (); - inline void Delete (T * object); - inline T * Head (); - inline const T * Head () const; - inline T * Next (const T * object); - inline const T * Next (const T * object) const; - inline void Order (T * linkedObject, ELinkType linkType, T * existingObject); - inline T * Prev (const T * object); - inline const T * Prev (const T * object) const; - inline T * Tail (); - inline const T * Tail () const; - inline void Unlink (T * object); - -}; - -//=========================================================================== -template -TBaseHashTable::TBaseHashTable () - : m_slotMask(), m_slotMaxCount(kDefaultSlotMaxCount), m_linkOffset() { - // more initialization done during call to SetLinkOffset() -} - -//=========================================================================== -template -TBaseHashTable::TBaseHashTable (const TBaseHashTable & source) { -#ifdef HS_DEBUGGING - FATAL("No copy constructor"); -#endif - TBaseHashTable(); -} - -//=========================================================================== -template -TBaseHashTable & TBaseHashTable::operator= (const TBaseHashTable & source) { -#ifdef HS_DEBUGGING - FATAL("No assignment operator"); -#endif - return *this; -} - -//=========================================================================== -template -void TBaseHashTable::Add (T * object, unsigned hash) { - GetHash(object) = hash; - - LIST(T) * list = &GetSlotList(hash); - if (CheckGrowTable(list)) - list = &GetSlotList(hash); - - m_fullList.Link(object); - list->Link(object); -} - -//=========================================================================== -template -bool TBaseHashTable::CheckGrowTable (LIST(T) * list) { - - unsigned nextCount = (m_slotMask + 1) * 2; - if (nextCount > m_slotMaxCount) - return false; - - unsigned listCount = 0; - for (T * curr = list->Head(); curr; curr = list->Next(curr)) - ++listCount; - - if (listCount + 1 < kGrowOnListSize) - return false; - - SetSlotCount(nextCount); - - return true; -} - -//=========================================================================== -template -void TBaseHashTable::Clear () { - m_fullList.Clear(); -} - -//=========================================================================== -template -void TBaseHashTable::Delete (T * object) { - delete object; -} - -//=========================================================================== -template -unsigned TBaseHashTable::GetHash (const T * object) const { - return GetLink(object).m_hash; -} - -//=========================================================================== -template -unsigned & TBaseHashTable::GetHash (T * object) { - return GetLink(object).m_hash; -} - -//=========================================================================== -template -const THashLink & TBaseHashTable::GetLink (const T * object) const { - return *(const THashLink *)((const uint8_t *)object + m_linkOffset); -} - -//=========================================================================== -template -THashLink & TBaseHashTable::GetLink (T * object) { - return *(THashLink *)((uint8_t *)object + m_linkOffset); -} - -//=========================================================================== -template -const LIST(T) & TBaseHashTable::GetSlotList (unsigned hash) const { - return m_slotListArray[hash & m_slotMask]; -} - -//=========================================================================== -template -LIST(T) & TBaseHashTable::GetSlotList (unsigned hash) { - return m_slotListArray[hash & m_slotMask]; -} - -//=========================================================================== -template -T * TBaseHashTable::Head () { - return m_fullList.Head(); -} - -//=========================================================================== -template -const T * TBaseHashTable::Head () const { - return m_fullList.Head(); -} - -//=========================================================================== -template -T * TBaseHashTable::Next (const T * object) { - return m_fullList.Next(object); -} - -//=========================================================================== -template -const T * TBaseHashTable::Next (const T * object) const { - return m_fullList.Next(object); -} - -//=========================================================================== -template -void TBaseHashTable::Order (T * linkedObject, ELinkType linkType, T * existingObject) { - THashLink & link = GetLink(linkedObject); - ASSERT(link.m_linkToFull.IsLinked()); - m_fullList.Link(linkedObject, linkType, existingObject); -} - -//=========================================================================== -template -T * TBaseHashTable::Prev (const T * object) { - return m_fullList.Prev(object); -} - -//=========================================================================== -template -const T * TBaseHashTable::Prev (const T * object) const { - return m_fullList.Prev(object); -} - -//=========================================================================== -template -void TBaseHashTable::SetLinkOffset (int linkOffset, unsigned maxSize) { - ASSERT(!m_fullList.Head()); - ASSERT(m_slotListArray.empty()); - ASSERT(!m_slotMask); - - m_linkOffset = linkOffset; - m_fullList.SetLinkOffset(m_linkOffset + offsetof(THashLink, m_linkToFull)); - - if (!m_slotMask) { - // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - uint32_t v = maxSize - 1; - v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; - v++; - - SetSlotCount(std::max(static_cast(kSlotMinCount), v)); - } -} - -//=========================================================================== -template -void TBaseHashTable::SetSlotCount (unsigned count) { - ASSERT(!(count & (count - 1))); // power of two - ASSERT(count >= 2); - - if (count == m_slotMask + 1) - return; - m_slotMask = count - 1; - - m_slotListArray.clear(); - m_slotListArray.resize(count); - for (unsigned loop = 0; loop < count; ++loop) - m_slotListArray[loop].SetLinkOffset(m_linkOffset + offsetof(THashLink, m_linkToSlot)); - - for (T * curr = Head(); curr; curr = Next(curr)) - GetSlotList(GetHash(curr)).Link(curr); -} - -//=========================================================================== -template -void TBaseHashTable::SetSlotMaxCount (unsigned count) { - if (count) - m_slotMaxCount = std::max(static_cast(kSlotMinCount), count); -} - -//=========================================================================== -template -T * TBaseHashTable::Tail () { - return m_fullList.Tail(); -} - -//=========================================================================== -template -const T * TBaseHashTable::Tail () const { - return m_fullList.Tail(); -} - -//=========================================================================== -template -void TBaseHashTable::Unlink (T * object) { - THashLink & link = GetLink(object); - link.Unlink(); -} - - -/**************************************************************************** -* -* THashTable -* -***/ - -template -class THashTable : public TBaseHashTable { - -public: - inline void Add (T * object); - inline void Add (T * object, unsigned hash); - inline T * Find (const K & key); - inline T * FindNext (const K & key, T * object); - inline const T * Find (const K & key) const; - inline const T * FindNext (const K & key, const T * object) const; - inline T * Unduplicate (T * object, const K & key); - -}; - -//=========================================================================== -template -inline void THashTable::Add (T * object) { - TBaseHashTable::Add(object, object->GetHash()); -} - -//=========================================================================== -template -inline void THashTable::Add (T * object, unsigned hash) { - TBaseHashTable::Add(object, hash); -} - -//=========================================================================== -template -T * THashTable::Find (const K & key) { - return (T *)((const THashTable *)this)->Find(key); -} - -//=========================================================================== -template -T * THashTable::FindNext (const K & key, T * object) { - return (T *)((const THashTable *)this)->FindNext(key, object); -} - -//=========================================================================== -template -const T * THashTable::Find (const K & key) const { - unsigned hash = key.GetHash(); - const LIST(T) & slotList = this->GetSlotList(hash); - for (const T * curr = slotList.Head(); curr; curr = slotList.Next(curr)) - if ((this->GetHash(curr) == hash) && (*curr == key)) - return curr; - return nullptr; -} - -//=========================================================================== -template -const T * THashTable::FindNext (const K & key, const T * object) const { - unsigned hash = key.GetHash(); - const LIST(T) & slotList = this->GetSlotList(hash); - for (const T * curr = slotList.Next(object); curr; curr = slotList.Next(curr)) - if ((this->GetHash(curr) == hash) && (*curr == key)) - return curr; - return nullptr; -} - -//=========================================================================== -template -T * THashTable::Unduplicate (T * object, const K & key) { - T * existing = Find(key); - if (existing) { - delete object; - return existing; - } - else { - Add(object); - return object; - } -} - - -/**************************************************************************** -* -* THashTableDecl -* -***/ - -template -class THashTableDecl : public THashTable { - -public: - inline THashTableDecl (); - -}; - -//=========================================================================== -template -THashTableDecl::THashTableDecl () { - this->SetLinkOffset(linkOffset, maxSize); - this->SetSlotMaxCount(maxSize); -} - - -/**************************************************************************** -* -* THashKeyVal -* -***/ - -template -class THashKeyVal { -public: - THashKeyVal () : m_value(0) { } - THashKeyVal (const T & value) : m_value(value) { } - bool operator== (const THashKeyVal & rhs) const { - return m_value == rhs.m_value; - } - unsigned GetHash () const { - CHashValue hash(&m_value, sizeof(m_value)); - return hash.GetHash(); - } - const T & GetValue () const { return m_value; } - void SetValue (const T & value) { m_value = value; } - -protected: - T m_value; -}; - -#endif diff --git a/Sources/Plasma/PubUtilLib/plVault/CMakeLists.txt b/Sources/Plasma/PubUtilLib/plVault/CMakeLists.txt index e24eeefa8a..a2fdddb6c4 100644 --- a/Sources/Plasma/PubUtilLib/plVault/CMakeLists.txt +++ b/Sources/Plasma/PubUtilLib/plVault/CMakeLists.txt @@ -31,7 +31,6 @@ target_link_libraries( pnAsyncCore pnDispatch pnNucleusInc - pnUtils plGImage plMessage plNetCommon diff --git a/Sources/Plasma/PubUtilLib/plVault/Pch.h b/Sources/Plasma/PubUtilLib/plVault/Pch.h index 7ef02ffad5..05f271e931 100644 --- a/Sources/Plasma/PubUtilLib/plVault/Pch.h +++ b/Sources/Plasma/PubUtilLib/plVault/Pch.h @@ -50,7 +50,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pnAsyncCore/pnAsyncCore.h" #include "pnNetProtocol/pnNetProtocol.h" -#include "pnUtils/pnUtils.h" #include "plVault.h" #include "plDniCoordinateInfo.h" diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp index 3b3446f6ed..04dc8a5ea5 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.cpp @@ -55,55 +55,23 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com * ***/ -struct IVaultCallback { - LINK(IVaultCallback) link; - VaultCallback * cb; -}; - -struct INotifyAfterDownload : THashKeyVal { - HASHLINK(INotifyAfterDownload) link; - unsigned parentId; - unsigned childId; - - INotifyAfterDownload (unsigned parentId, unsigned childId) - : THashKeyVal(childId) - , parentId(parentId) - , childId(childId) - {} -}; - -// A RelVaultNodeLink may be either stored in the global table, -// or stored in an IRelVaultNode's parents or children table. -struct RelVaultNodeLink : THashKeyVal { - HASHLINK(RelVaultNodeLink) link; +// A RelVaultNodeLink is stored in an IRelVaultNode's children table. +struct RelVaultNodeLink { hsRef node; unsigned ownerId; bool seen; - RelVaultNodeLink(bool seen, unsigned ownerId, unsigned nodeId) - : THashKeyVal(nodeId), node(new RelVaultNode, hsStealRef), ownerId(ownerId), seen(seen) - { } - - RelVaultNodeLink (bool seen, unsigned ownerId, unsigned nodeId, hsRef node) - : THashKeyVal(nodeId), node(std::move(node)), ownerId(ownerId), seen(seen) + RelVaultNodeLink(bool seen, unsigned ownerId, hsRef node) + : node(std::move(node)), ownerId(ownerId), seen(seen) { } }; struct IRelVaultNode { hsWeakRef node; - - HASHTABLEDECL( - RelVaultNodeLink, - THashKeyVal, - link - ) parents; - - HASHTABLEDECL( - RelVaultNodeLink, - THashKeyVal, - link - ) children; + + std::unordered_map> parents; + std::unordered_map children; IRelVaultNode(hsWeakRef node); ~IRelVaultNode (); @@ -279,29 +247,15 @@ struct AddChildNodeFetchTrans { * ***/ -static bool s_running; +std::unordered_map> s_nodes; -static HASHTABLEDECL( - RelVaultNodeLink, - THashKeyVal, - link -) s_nodes; +std::list s_callbacks; -static LISTDECL( - IVaultCallback, - link -) s_callbacks; - -static HASHTABLEDECL( - INotifyAfterDownload, - THashKeyVal, - link -) s_notifyAfterDownload; +// key: childId, value: parentId +std::unordered_map s_notifyAfterDownload; static std::unordered_map s_ageDeviceInboxes; -static bool s_processPlayerInbox = false; - static std::atomic s_suppressCallbacks; /***************************************************************************** @@ -329,30 +283,33 @@ static void VaultNodeFound ( static void VaultNodeAddedDownloadCallback(ENetError result, void * param) { unsigned childId = (unsigned)((uintptr_t)param); - INotifyAfterDownload* notify = s_notifyAfterDownload.Find(childId); + auto it = s_notifyAfterDownload.find(childId); - if (notify) { + if (it != s_notifyAfterDownload.end()) { + unsigned parentId = it->second; if (IS_NET_SUCCESS(result)) { - RelVaultNodeLink* parentLink = s_nodes.Find(notify->parentId); - RelVaultNodeLink* childLink = s_nodes.Find(notify->childId); - - if (parentLink && childLink) { - if (childLink->node->GetNodeType() == plVault::kNodeType_TextNote) { - VaultTextNoteNode textNote(childLink->node); - if (textNote.GetNoteType() == plVault::kNoteType_Visit) - VaultProcessVisitNote(childLink->node); - else if (textNote.GetNoteType() == plVault::kNoteType_UnVisit) - VaultProcessUnvisitNote(childLink->node); + auto parentIt = s_nodes.find(parentId); + auto childIt = s_nodes.find(childId); + + if (parentIt != s_nodes.end() && childIt != s_nodes.end()) { + const hsRef& parentNode = parentIt->second; + const hsRef& childNode = childIt->second; + if (childNode->GetNodeType() == plVault::kNodeType_TextNote) { + VaultTextNoteNode textNote(childNode); + if (textNote.GetNoteType() == plVault::kNoteType_Visit) { + VaultProcessVisitNote(childNode); + } else if (textNote.GetNoteType() == plVault::kNoteType_UnVisit) { + VaultProcessUnvisitNote(childNode); + } } if (s_suppressCallbacks == 0) { - for (IVaultCallback* cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->AddedChildNode(parentLink->node, childLink->node); + for (auto cb : s_callbacks) { + cb->AddedChildNode(parentNode, childNode); + } } } } - - delete notify; } } @@ -367,57 +324,51 @@ static void BuildNodeTree ( ) { for (unsigned i = 0; i < refCount; ++i) { // Find/Create global links - RelVaultNodeLink * parentLink = s_nodes.Find(refs[i].parentId); - if (!parentLink) { + auto parentIt = s_nodes.find(refs[i].parentId); + if (parentIt == s_nodes.end()) { newNodeIds->emplace_back(refs[i].parentId); - parentLink = new RelVaultNodeLink(false, 0, refs[i].parentId); - parentLink->node->SetNodeId_NoDirty(refs[i].parentId); - s_nodes.Add(parentLink); - } - else { + hsRef newParentNode(new RelVaultNode(), hsStealRef); + newParentNode->SetNodeId_NoDirty(refs[i].parentId); + parentIt = s_nodes.emplace(refs[i].parentId, std::move(newParentNode)).first; + } else { existingNodeIds->emplace_back(refs[i].parentId); } - RelVaultNodeLink * childLink = s_nodes.Find(refs[i].childId); - if (!childLink) { + const hsRef& parentNode = parentIt->second; + + auto childIt = s_nodes.find(refs[i].childId); + if (childIt == s_nodes.end()) { newNodeIds->emplace_back(refs[i].childId); - childLink = new RelVaultNodeLink(refs[i].seen, refs[i].ownerId, refs[i].childId); - childLink->node->SetNodeId_NoDirty(refs[i].childId); - s_nodes.Add(childLink); - } - else { + hsRef newChildNode(new RelVaultNode(), hsStealRef); + newChildNode->SetNodeId_NoDirty(refs[i].childId); + childIt = s_nodes.emplace(refs[i].childId, std::move(newChildNode)).first; + } else { existingNodeIds->emplace_back(refs[i].childId); - if (unsigned ownerId = refs[i].ownerId) - childLink->ownerId = ownerId; } + const hsRef& childNode = childIt->second; - hsRef parentNode = parentLink->node; - hsRef childNode = childLink->node; - bool isImmediateParent = parentNode->IsParentOf(refs[i].childId, 1); bool isImmediateChild = childNode->IsChildOf(refs[i].parentId, 1); if (!isImmediateParent) { // Add parent to child's parents table - parentLink = new RelVaultNodeLink(false, 0, parentNode->GetNodeId(), parentNode); - childNode->state->parents.Add(parentLink); + childNode->state->parents.emplace(parentNode->GetNodeId(), parentNode); LogMsg(kLogDebug, "Added relationship: p:{},c:{}", refs[i].parentId, refs[i].childId); } if (!isImmediateChild) { // Add child to parent's children table - childLink = new RelVaultNodeLink(refs[i].seen, refs[i].ownerId, childNode->GetNodeId(), childNode); - parentNode->state->children.Add(childLink); + parentNode->state->children.emplace(childNode->GetNodeId(), RelVaultNodeLink(refs[i].seen, refs[i].ownerId, childNode)); if (notifyNow || childNode->GetNodeType() != 0) { // We made a new link, so make the callbacks if (s_suppressCallbacks == 0) { - for (IVaultCallback* cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->AddedChildNode(parentNode, childNode); + for (auto cb : s_callbacks) { + cb->AddedChildNode(parentNode, childNode); + } } } else { - INotifyAfterDownload* notify = new INotifyAfterDownload(parentNode->GetNodeId(), childNode->GetNodeId()); - s_notifyAfterDownload.Add(notify); + s_notifyAfterDownload.emplace(childNode->GetNodeId(), parentNode->GetNodeId()); } } } @@ -495,13 +446,15 @@ static void FetchNodesFromRefs ( // Fetch the nodes that do not yet have a nodetype unsigned prevId = 0; for (unsigned nodeId : nodeIds) { - RelVaultNodeLink * link = s_nodes.Find(nodeId); - if (link->node->GetNodeType() != 0) + const hsRef& node = s_nodes.at(nodeId); + if (node->GetNodeType() != 0) { continue; + } // filter duplicates - if (link->node->GetNodeId() == prevId) + if (node->GetNodeId() == prevId) { continue; - prevId = link->node->GetNodeId(); + } + prevId = node->GetNodeId(); NetCliAuthVaultNodeFetch( nodeId, fetchCallback, @@ -527,8 +480,9 @@ static void VaultNodeFound ( for (unsigned i = 0; i < nodeIdCount; ++i) { // See if we already have this node - if (RelVaultNodeLink * link = s_nodes.Find(nodeIds[i])) + if (s_nodes.find(nodeIds[i]) != s_nodes.end()) { return; + } // Start fetching the node NetCliAuthVaultNodeFetch(nodeIds[i], VaultNodeFetched, nullptr); @@ -547,16 +501,17 @@ static void VaultNodeFetched ( } // Add to global node table - RelVaultNodeLink * link = s_nodes.Find(node->GetNodeId()); - if (!link) { - link = new RelVaultNodeLink(false, 0, node->GetNodeId()); - link->node->SetNodeId_NoDirty(node->GetNodeId()); - s_nodes.Add(link); + auto it = s_nodes.find(node->GetNodeId()); + if (it == s_nodes.end()) { + hsRef newGlobalNode(new RelVaultNode(), hsStealRef); + newGlobalNode->SetNodeId_NoDirty(node->GetNodeId()); + it = s_nodes.emplace(node->GetNodeId(), std::move(newGlobalNode)).first; } - link->node->CopyFrom(node); - InitFetchedNode(link->node); + const hsRef& globalNode = it->second; + globalNode->CopyFrom(node); + InitFetchedNode(globalNode); - link->node->Print("Fetched", 0); + globalNode->Print("Fetched", 0); } //============================================================================ @@ -572,15 +527,17 @@ static void ChangedVaultNodeFetched ( VaultNodeFetched(result, param, node); - RelVaultNodeLink* savedLink = s_nodes.Find(node->GetNodeId()); + auto it = s_nodes.find(node->GetNodeId()); // Yeah, we are purposefully allowing this global callback to go out, // even if callback suppression has been enabled. The intent behind // that is to suppress spurious callbacks, but node changes are // probably not spurious. - if (savedLink) { - for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->ChangedNode(savedLink->node); + if (it != s_nodes.end()) { + const hsRef& savedNode = it->second; + for (auto cb : s_callbacks) { + cb->ChangedNode(savedNode); + } } } @@ -591,22 +548,24 @@ static void VaultNodeChanged ( ) { LogMsg(kLogDebug, "Notify: Node changed: {}", nodeId); - RelVaultNodeLink * link = s_nodes.Find(nodeId); + auto it = s_nodes.find(nodeId); // We don't have the node, so we don't care that it changed (we actually // shouldn't have been notified) - if (!link) { + if (it == s_nodes.end()) { LogMsg(kLogDebug, "rcvd change notification for node {}, but node doesn't exist locally.", nodeId); return; } + const hsRef& node = it->second; - if (link->node->GetRevision() == revisionId) { + if (node->GetRevision() == revisionId) { // We are the party responsible for the change, so we already have the // latest version of the node; no need to fetch it. However, we do need to fire off // the "hey this was saved" callback. if (s_suppressCallbacks == 0) { - for (IVaultCallback* cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->ChangedNode(link->node); + for (auto cb : s_callbacks) { + cb->ChangedNode(node); + } } } else { // We have the node and we weren't the one that changed it, so fetch it. @@ -648,13 +607,15 @@ static void VaultNodeAdded ( unsigned prevId = 0; unsigned i = 0; for (; i < nodeIds.size(); ++i) { - RelVaultNodeLink * link = s_nodes.Find(nodeIds[i]); - if (link->node->GetNodeType() != 0) + const hsRef& node = s_nodes.at(nodeIds[i]); + if (node->GetNodeType() != 0) { continue; + } // filter duplicates - if (link->node->GetNodeId() == prevId) + if (node->GetNodeId() == prevId) { continue; - prevId = link->node->GetNodeId(); + } + prevId = node->GetNodeId(); VaultDownload( "NodeAdded", nodeIds[i], @@ -665,20 +626,18 @@ static void VaultNodeAdded ( ); } - if (parentId == inboxId) { - if (i > 0) - s_processPlayerInbox = true; - else - VaultProcessPlayerInbox(); + if (parentId == inboxId && i == 0) { + VaultProcessPlayerInbox(); } // if the added element is already downloaded then send the callbacks now - RelVaultNodeLink* parentLink = s_nodes.Find(parentId); - RelVaultNodeLink* childLink = s_nodes.Find(childId); + const hsRef& parentNode = s_nodes.at(parentId); + const hsRef& childNode = s_nodes.at(childId); - if (childLink->node->GetNodeType() != 0 && s_suppressCallbacks == 0) { - for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->AddedChildNode(parentLink->node, childLink->node); + if (childNode->GetNodeType() != 0 && s_suppressCallbacks == 0) { + for (auto cb : s_callbacks) { + cb->AddedChildNode(parentNode, childNode); + } } } @@ -690,22 +649,27 @@ static void VaultNodeRemoved ( LogMsg(kLogDebug, "Notify: Node removed: p:{},c:{}", parentId, childId); for (;;) { // Unlink 'em locally, if we can - RelVaultNodeLink * parentLink = s_nodes.Find(parentId); - if (!parentLink) + auto parentIt = s_nodes.find(parentId); + if (parentIt == s_nodes.end()) { break; + } - RelVaultNodeLink * childLink = s_nodes.Find(childId); - if (!childLink) + auto childIt = s_nodes.find(childId); + if (childIt == s_nodes.end()) { break; - - if (parentLink->node->IsParentOf(childId, 1) && s_suppressCallbacks == 0) { + } + + const hsRef& parentNode = parentIt->second; + const hsRef& childNode = childIt->second; + if (parentNode->IsParentOf(childId, 1) && s_suppressCallbacks == 0) { // We have the relationship, so make the callbacks - for (IVaultCallback * cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->RemovingChildNode(parentLink->node, childLink->node); + for (auto cb : s_callbacks) { + cb->RemovingChildNode(parentNode, childNode); + } } - - parentLink->node->state->Unlink(childLink->node); - childLink->node->state->Unlink(parentLink->node); + + parentNode->state->Unlink(childNode); + childNode->state->Unlink(parentNode); break; } } @@ -728,13 +692,13 @@ static void SaveDirtyNodes () { if (!s_nextSaveMs || signed(s_nextSaveMs - currTimeMs) <= 0) { s_nextSaveMs = (currTimeMs + kSaveUpdateIntervalMs) | 1; unsigned bytesWritten = 0; - for (RelVaultNodeLink * link = s_nodes.Head(); link; link = s_nodes.Next(link)) { + for (const auto& [nodeId, node] : s_nodes) { if (bytesWritten >= kMaxBytesPerSaveUpdate) break; - if (link->node->IsDirty()) { - if (unsigned bytes = NetCliAuthVaultNodeSave(link->node.Get(), nullptr, nullptr); bytes) { + if (node->IsDirty()) { + if (unsigned bytes = NetCliAuthVaultNodeSave(node.Get(), nullptr, nullptr); bytes) { bytesWritten += bytes; - link->node->Print("Saving", 0); + node->Print("Saving", 0); } } } @@ -802,10 +766,11 @@ void VaultCreateNodeTrans::VaultNodeFetched ( VaultCreateNodeTrans * trans = (VaultCreateNodeTrans *)param; - if (IS_NET_SUCCESS(result)) - trans->node = s_nodes.Find(node->GetNodeId())->node; - else + if (IS_NET_SUCCESS(result)) { + trans->node = s_nodes.at(node->GetNodeId()); + } else { trans->node = nullptr; + } trans->Complete(result); } @@ -921,8 +886,8 @@ void VaultDownloadTrans::VaultNodeRefsFetched ( } else { // root node has no child heirarchy? Make sure we still d/l the root node if necessary. - RelVaultNodeLink* rootNodeLink = s_nodes.Find(trans->vaultId); - if (!rootNodeLink || rootNodeLink->node->GetNodeType() == 0) { + auto rootNodeIt = s_nodes.find(trans->vaultId); + if (rootNodeIt == s_nodes.end() || rootNodeIt->second->GetNodeType() == 0) { NetCliAuthVaultNodeFetch( trans->vaultId, VaultDownloadTrans::VaultNodeFetched, @@ -1052,53 +1017,60 @@ IRelVaultNode::IRelVaultNode(hsWeakRef node) //============================================================================ IRelVaultNode::~IRelVaultNode () { - ASSERT(!parents.Head()); - ASSERT(!children.Head()); + ASSERT(parents.empty()); + ASSERT(children.empty()); } //============================================================================ void IRelVaultNode::UnlinkFromRelatives () { - - RelVaultNodeLink * link, * next; - for (link = parents.Head(); link; link = next) { - next = parents.Next(link); + for (auto it = parents.begin(); it != parents.end();) { + // Advance the iterator before calling Unlink so that it doesn't get invalidated + hsWeakRef parentNode = it->second; + ++it; // We have the relationship, so make the callbacks if (s_suppressCallbacks == 0) { - for (IVaultCallback* cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->RemovingChildNode(link->node, this->node); + for (auto cb : s_callbacks) { + cb->RemovingChildNode(parentNode, this->node); + } } - link->node->state->Unlink(node); + parentNode->state->Unlink(node); } - for (link = children.Head(); link; link = next) { - next = children.Next(link); - link->node->state->Unlink(node); + for (auto it = children.begin(); it != children.end();) { + // Advance the iterator before calling Unlink so that it doesn't get invalidated + hsWeakRef childNode = it->second.node; + ++it; + childNode->state->Unlink(node); } - - ASSERT(!parents.Head()); - ASSERT(!children.Head()); + + ASSERT(parents.empty()); + ASSERT(children.empty()); } //============================================================================ void IRelVaultNode::Unlink(hsWeakRef other) { ASSERT(other != node); - - RelVaultNodeLink * link; - if (link = parents.Find(other->GetNodeId()); link != nullptr) { + + auto parentIt = parents.find(other->GetNodeId()); + if (parentIt != parents.end()) { + // Grab the node ref - the erase call will invalidate the iterator! + hsRef parentNode = std::move(parentIt->second); // make them non-findable in our parents table - link->link.Unlink(); + parents.erase(parentIt); // remove us from other's tables. - link->node->state->Unlink(node); - delete link; + parentNode->state->Unlink(node); } - if (link = children.Find(other->GetNodeId()); link != nullptr) { + + auto childIt = children.find(other->GetNodeId()); + if (childIt != children.end()) { + // Grab the node ref - the erase call will invalidate the iterator! + hsRef childNode = std::move(childIt->second.node); // make them non-findable in our children table - link->link.Unlink(); + children.erase(childIt); // remove us from other's tables. - link->node->state->Unlink(node); - delete link; + childNode->state->Unlink(node); } } @@ -1124,12 +1096,13 @@ bool RelVaultNode::IsParentOf (unsigned childId, unsigned maxDepth) { return false; if (maxDepth == 0) return false; - if (state->children.Find(childId)) + if (state->children.find(childId) != state->children.end()) return true; - RelVaultNodeLink * link = state->children.Head(); - for (; link; link = state->children.Next(link)) - if (link->node->IsParentOf(childId, maxDepth - 1)) + for (const auto& [nodeId, link] : state->children) { + if (link.node->IsParentOf(childId, maxDepth - 1)) { return true; + } + } return false; } @@ -1139,24 +1112,24 @@ bool RelVaultNode::IsChildOf (unsigned parentId, unsigned maxDepth) { return false; if (maxDepth == 0) return false; - if (state->parents.Find(parentId)) + if (state->parents.find(parentId) != state->parents.end()) return true; - RelVaultNodeLink * link = state->parents.Head(); - for (; link; link = state->parents.Next(link)) - if (link->node->IsChildOf(parentId, maxDepth - 1)) + for (const auto& [nodeId, node] : state->parents) { + if (node->IsChildOf(parentId, maxDepth - 1)) { return true; + } + } return false; } //============================================================================ void RelVaultNode::GetRootIds (std::vector * nodeIds) { - RelVaultNodeLink * link = state->parents.Head(); - if (!link) { + if (state->parents.empty()) { nodeIds->emplace_back(GetNodeId()); - } - else { - for (; link; link = state->parents.Next(link)) - link->node->GetRootIds(nodeIds); + } else { + for (const auto& [nodeId, node] : state->parents) { + node->GetRootIds(nodeIds); + } } } @@ -1173,10 +1146,9 @@ void RelVaultNode::GetChildNodeIds ( ) { if (!maxDepth) return; - RelVaultNodeLink * link = state->children.Head(); - for (; link; link = state->children.Next(link)) { - nodeIds->emplace_back(link->node->GetNodeId()); - link->node->GetChildNodeIds(nodeIds, maxDepth-1); + for (const auto& [nodeId, link] : state->children) { + nodeIds->emplace_back(link.node->GetNodeId()); + link.node->GetChildNodeIds(nodeIds, maxDepth-1); } } @@ -1187,10 +1159,9 @@ void RelVaultNode::GetParentNodeIds ( ) { if (!maxDepth) return; - RelVaultNodeLink * link = state->parents.Head(); - for (; link; link = state->parents.Next(link)) { - nodeIds->emplace_back(link->node->GetNodeId()); - link->node->GetParentNodeIds(nodeIds, maxDepth-1); + for (const auto& [nodeId, node] : state->parents) { + nodeIds->emplace_back(node->GetNodeId()); + node->GetParentNodeIds(nodeIds, maxDepth-1); } } @@ -1203,17 +1174,16 @@ hsRef RelVaultNode::GetParentNode ( if (maxDepth == 0) return nullptr; - RelVaultNodeLink * link; - link = state->parents.Head(); - for (; link; link = state->parents.Next(link)) { - if (link->node->Matches(templateNode.Get())) - return link->node; - } - - link = state->parents.Head(); - for (; link; link = state->parents.Next(link)) { - if (hsRef node = link->node->GetParentNode(templateNode, maxDepth - 1)) + for (const auto& [nodeId, node] : state->parents) { + if (node->Matches(templateNode.Get())) { return node; + } + } + + for (const auto& [nodeId, node] : state->parents) { + if (hsRef parentNode = node->GetParentNode(templateNode, maxDepth - 1)) { + return parentNode; + } } return nullptr; @@ -1227,17 +1197,16 @@ hsRef RelVaultNode::GetChildNode ( if (maxDepth == 0) return nullptr; - RelVaultNodeLink * link; - link = state->children.Head(); - for (; link; link = state->children.Next(link)) { - if (link->node->Matches(templateNode.Get())) - return link->node; + for (const auto& [nodeId, link] : state->children) { + if (link.node->Matches(templateNode.Get())) { + return link.node; + } } - - link = state->children.Head(); - for (; link; link = state->children.Next(link)) { - if (hsRef node = link->node->GetChildNode(templateNode, maxDepth-1)) + + for (const auto& [nodeId, link] : state->children) { + if (hsRef node = link.node->GetChildNode(templateNode, maxDepth - 1)) { return node; + } } return nullptr; @@ -1297,11 +1266,9 @@ void RelVaultNode::GetChildNodes ( if (maxDepth == 0) return; - RelVaultNodeLink * link; - link = state->children.Head(); - for (; link; link = state->children.Next(link)) { - nodes->push_back(link->node); - link->node->GetChildNodes( + for (const auto& [nodeId, link] : state->children) { + nodes->push_back(link.node); + link.node->GetChildNodes( maxDepth - 1, nodes ); @@ -1314,13 +1281,12 @@ void RelVaultNode::GetChildNodes ( unsigned maxDepth, RelVaultNode::RefList * nodes ) { - RelVaultNodeLink * link; - link = state->children.Head(); - for (; link; link = state->children.Next(link)) { - if (link->node->Matches(templateNode.Get())) - nodes->push_back(link->node); + for (const auto& [nodeId, link] : state->children) { + if (link.node->Matches(templateNode.Get())) { + nodes->push_back(link.node); + } - link->node->GetChildNodes( + link.node->GetChildNodes( templateNode, maxDepth - 1, nodes @@ -1363,30 +1329,46 @@ void RelVaultNode::GetChildFolderNodes ( //============================================================================ unsigned RelVaultNode::GetRefOwnerId (unsigned parentId) { // find our parents' link to us and return its ownerId - if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) - if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) - return childLink->ownerId; + auto parentIt = state->parents.find(parentId); + if (parentIt != state->parents.end()) { + const hsRef& parentNode = parentIt->second; + auto childIt = parentNode->state->children.find(GetNodeId()); + if (childIt != parentNode->state->children.end()) { + return childIt->second.ownerId; + } + } return 0; } //============================================================================ bool RelVaultNode::BeenSeen (unsigned parentId) const { // find our parents' link to us and return its seen flag - if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) - if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) - return childLink->seen; + auto parentIt = state->parents.find(parentId); + if (parentIt != state->parents.end()) { + const hsRef& parentNode = parentIt->second; + auto childIt = parentNode->state->children.find(GetNodeId()); + if (childIt != parentNode->state->children.end()) { + return childIt->second.seen; + } + } return true; } //============================================================================ void RelVaultNode::SetSeen (unsigned parentId, bool seen) { // find our parents' link to us and set its seen flag - if (RelVaultNodeLink * parentLink = state->parents.Find(parentId)) - if (RelVaultNodeLink * childLink = parentLink->node->state->children.Find(GetNodeId())) - if (childLink->seen != seen) { - childLink->seen = seen; + auto parentIt = state->parents.find(parentId); + if (parentIt != state->parents.end()) { + const hsRef& parentNode = parentIt->second; + auto childIt = parentNode->state->children.find(GetNodeId()); + if (childIt != parentNode->state->children.end()) { + RelVaultNodeLink& childLink = childIt->second; + if (childLink.seen != seen) { + childLink.seen = seen; NetCliAuthVaultSetSeen(parentId, GetNodeId(), seen); } + } + } } //============================================================================ @@ -1465,8 +1447,9 @@ void RelVaultNode::Print (const ST::string& tag, unsigned level) { //============================================================================ void RelVaultNode::PrintTree (unsigned level) { Print("", level); - for (RelVaultNodeLink * link = state->children.Head(); link; link = state->children.Next(link)) - link->node->PrintTree(level + 1); + for (const auto& [nodeId, link] : state->children) { + link.node->PrintTree(level + 1); + } } //============================================================================ @@ -1497,17 +1480,14 @@ hsRef RelVaultNode::GetParentAgeLink () { //============================================================================ void VaultRegisterCallback (VaultCallback * cb) { - IVaultCallback * internal = new IVaultCallback; - internal->cb = cb; - cb->internal = internal; - s_callbacks.Link(internal); + s_callbacks.emplace_back(cb); } //============================================================================ void VaultUnregisterCallback (VaultCallback * cb) { - ASSERT(cb->internal); - delete cb->internal; - cb->internal = nullptr; + auto it = std::find(s_callbacks.begin(), s_callbacks.end(), cb); + ASSERT(it != s_callbacks.end()); + s_callbacks.erase(it); } //============================================================================ @@ -1529,8 +1509,6 @@ void VaultEnableCallbacks() { //============================================================================ void VaultInitialize () { - s_running = true; - NetCliAuthVaultSetRecvNodeChangedHandler(VaultNodeChanged); NetCliAuthVaultSetRecvNodeAddedHandler(VaultNodeAdded); NetCliAuthVaultSetRecvNodeRemovedHandler(VaultNodeRemoved); @@ -1539,20 +1517,16 @@ void VaultInitialize () { //============================================================================ void VaultDestroy () { - s_running = false; - NetCliAuthVaultSetRecvNodeChangedHandler(nullptr); NetCliAuthVaultSetRecvNodeAddedHandler(nullptr); NetCliAuthVaultSetRecvNodeRemovedHandler(nullptr); NetCliAuthVaultSetRecvNodeDeletedHandler(nullptr); VaultClearDeviceInboxMap(); - - RelVaultNodeLink * next, * link = s_nodes.Head(); - for (; link; link = next) { - next = s_nodes.Next(link); - link->node->state->UnlinkFromRelatives(); - delete link; + + for (auto it = s_nodes.begin(); it != s_nodes.end();) { + it->second->state->UnlinkFromRelatives(); + it = s_nodes.erase(it); } } @@ -1573,11 +1547,10 @@ hsRef VaultGetNode ( hsWeakRef templateNode ) { ASSERT(templateNode); - RelVaultNodeLink * link = s_nodes.Head(); - while (link) { - if (link->node->Matches(templateNode.Get())) - return link->node; - link = s_nodes.Next(link); + for (const auto& [nodeId, node] : s_nodes) { + if (node->Matches(templateNode.Get())) { + return node; + } } return nullptr; } @@ -1586,9 +1559,8 @@ hsRef VaultGetNode ( hsRef VaultGetNode ( unsigned nodeId ) { - if (RelVaultNodeLink * link = s_nodes.Find(nodeId)) - return link->node; - return nullptr; + auto it = s_nodes.find(nodeId); + return it == s_nodes.end() ? nullptr : it->second; } //============================================================================ @@ -1610,16 +1582,16 @@ void VaultAddChildNode ( // This directly affects: New clothing items added to the avatar outfit folder, // new chronicle entries in some ages, and I'm sure several other situations. - if (RelVaultNodeLink * parentLink = s_nodes.Find(parentId)) { - RelVaultNodeLink * childLink = s_nodes.Find(childId); - if (!childLink) { - childLink = new RelVaultNodeLink(false, ownerId, childId); - childLink->node->SetNodeId_NoDirty(childId); - s_nodes.Add(childLink); - } - else if (ownerId) { - childLink->ownerId = ownerId; + auto parentIt = s_nodes.find(parentId); + if (parentIt != s_nodes.end()) { + const hsRef& parentNode = parentIt->second; + auto childIt = s_nodes.find(childId); + if (childIt == s_nodes.end()) { + hsRef newChildNode(new RelVaultNode(), hsStealRef); + newChildNode->SetNodeId_NoDirty(childId); + childIt = s_nodes.emplace(childId, std::move(newChildNode)).first; } + const hsRef& childNode = childIt->second; // We can do a sanity check for a would-be circular link, but it isn't // authoritative. The db will prevent circular links from entering into @@ -1627,13 +1599,13 @@ void VaultAddChildNode ( // before the authoritative check, we're risking the local client operating // on bad, possibly harmful vault state. Not harmful in a national security // kinda way, but still harmful. - if (parentLink->node->IsChildOf(childId, 255)) { + if (parentNode->IsChildOf(childId, 255)) { LogMsg(kLogDebug, "Node relationship would be circular: p:{}, c:{}", parentId, childId); // callback now with error code if (callback) callback(kNetErrCircularReference, param); } - else if (childLink->node->IsParentOf(parentId, 255)) { + else if (childNode->IsParentOf(parentId, 255)) { LogMsg(kLogDebug, "Node relationship would be circular: p:{}, c:{}", parentId, childId); // callback now with error code if (callback) @@ -1649,10 +1621,10 @@ void VaultAddChildNode ( BuildNodeTree(refs, std::size(refs), &newNodeIds, &existingNodeIds); - if (!childLink->node->GetNodeType() || !parentLink->node->GetNodeType()) { + if (!childNode->GetNodeType() || !parentNode->GetNodeType()) { // One or more nodes need to be fetched before the callback is made AddChildNodeFetchTrans * trans = new AddChildNodeFetchTrans(callback, param); - if (!childLink->node->GetNodeType()) { + if (!childNode->GetNodeType()) { ++trans->opCount; NetCliAuthVaultNodeFetch( childId, @@ -1666,7 +1638,7 @@ void VaultAddChildNode ( trans ); } - if (!parentLink->node->GetNodeType()) { + if (!parentNode->GetNodeType()) { ++trans->opCount; NetCliAuthVaultNodeFetch( parentId, @@ -1767,24 +1739,29 @@ void VaultRemoveChildNode ( ) { for (;;) { // Unlink 'em locally, if we can - RelVaultNodeLink * parentLink = s_nodes.Find(parentId); - if (!parentLink) + auto parentIt = s_nodes.find(parentId); + if (parentIt == s_nodes.end()) { break; + } - RelVaultNodeLink * childLink = s_nodes.Find(childId); - if (!childLink) + auto childIt = s_nodes.find(childId); + if (childIt == s_nodes.end()) { break; - - if (parentLink->node->IsParentOf(childId, 1)) { + } + + const hsRef& parentNode = parentIt->second; + const hsRef& childNode = childIt->second; + if (parentNode->IsParentOf(childId, 1)) { // We have the relationship, so make the callbacks if (s_suppressCallbacks == 0) { - for (IVaultCallback* cb = s_callbacks.Head(); cb; cb = s_callbacks.Next(cb)) - cb->cb->RemovingChildNode(parentLink->node, childLink->node); + for (auto cb : s_callbacks) { + cb->RemovingChildNode(parentNode, childNode); + } } } - - parentLink->node->state->Unlink(childLink->node); - childLink->node->state->Unlink(parentLink->node); + + parentNode->state->Unlink(childNode); + childNode->state->Unlink(parentNode); break; } @@ -2050,9 +2027,10 @@ void VaultLocalFindNodes ( hsWeakRef templateNode, std::vector * nodeIds ) { - for (RelVaultNodeLink * link = s_nodes.Head(); link != nullptr; link = s_nodes.Next(link)) { - if (link->node->Matches(templateNode.Get())) - nodeIds->emplace_back(link->node->GetNodeId()); + for (const auto& [nodeId, node] : s_nodes) { + if (node->Matches(templateNode.Get())) { + nodeIds->emplace_back(node->GetNodeId()); + } } } @@ -2084,7 +2062,7 @@ void VaultFetchNodesAndWait ( if (!force) { // See if we already have this node - if (RelVaultNodeLink * link = s_nodes.Find(nodeIds[i])) { + if (s_nodes.find(nodeIds[i]) != s_nodes.end()) { --nodeCount; continue; } @@ -4697,33 +4675,41 @@ void VaultCull (unsigned vaultId) { VaultCallbackSuppressor suppress; // Remove the node from the global table - if (RelVaultNodeLink * link = s_nodes.Find(vaultId)) { - LogMsg(kLogDebug, "Vault: Culling node {}", link->node->GetNodeId()); - link->node->state->UnlinkFromRelatives(); - delete link; + auto nodeIt = s_nodes.find(vaultId); + if (nodeIt != s_nodes.end()) { + LogMsg(kLogDebug, "Vault: Culling node {}", nodeIt->first); + nodeIt->second->state->UnlinkFromRelatives(); + s_nodes.erase(nodeIt); } // Remove all orphaned nodes from the global table - for (RelVaultNodeLink * next, * link = s_nodes.Head(); link; link = next) { - next = s_nodes.Next(link); + for (auto it = s_nodes.begin(); it != s_nodes.end();) { + const hsRef& node = it->second; - if (link->node->GetNodeType() > plVault::kNodeType_VNodeMgrLow && link->node->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) + if (node->GetNodeType() > plVault::kNodeType_VNodeMgrLow && node->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) { + ++it; continue; + } std::vector nodeIds; - link->node->GetRootIds(&nodeIds); + node->GetRootIds(&nodeIds); bool foundRoot = false; for (unsigned nodeId : nodeIds) { - RelVaultNodeLink * root = s_nodes.Find(nodeId); - if (root && root->node->GetNodeType() > plVault::kNodeType_VNodeMgrLow && root->node->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) { - foundRoot = true; - break; + auto rootIt = s_nodes.find(nodeId); + if (rootIt != s_nodes.end()) { + const hsRef& root = rootIt->second; + if (root->GetNodeType() > plVault::kNodeType_VNodeMgrLow && root->GetNodeType() < plVault::kNodeType_VNodeMgrHigh) { + foundRoot = true; + break; + } } } if (!foundRoot) { - LogMsg(kLogDebug, "Vault: Culling node {}", link->node->GetNodeId()); - link->node->state->UnlinkFromRelatives(); - delete link; + LogMsg(kLogDebug, "Vault: Culling node {}", it->first); + node->state->UnlinkFromRelatives(); + it = s_nodes.erase(it); + } else { + ++it; } } } diff --git a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h index 3f069a33f3..90995cee57 100644 --- a/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h +++ b/Sources/Plasma/PubUtilLib/plVault/plVaultClientApi.h @@ -62,8 +62,6 @@ struct RelVaultNode; class plUUID; struct VaultCallback { - struct IVaultCallback * internal; - virtual ~VaultCallback() { } virtual void AddedChildNode (