diff --git a/CMakeLists.txt b/CMakeLists.txt index eec39ac4b..e52e96e28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ SET (CMAKE_NO_GIT_REVISION false CACHE BOOL "Do not try to retrieve the current SET (WIN32_SPAWN_CONSOLE false CACHE BOOL "Spawn an additional console, useful for debugging.") SET (USE_ASAN false CACHE BOOL "Enable AddressSanitizer.") +SET (USE_MSAN false CACHE BOOL "Enable MemorySanitizer.") SET (USE_LSAN false CACHE BOOL "Enable LeakSanitizer.") SET (USE_UBSAN false CACHE BOOL "Enable Undefined Behavior Sanitizer.") diff --git a/Changelog.txt b/Changelog.txt index 9e74e3d91..929252b0a 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -3380,3 +3380,8 @@ Additionally, the problem of zig-zag issue following in the South direction has 08-10-2023, Nolok & xwerswoodx - Fixed: Setting P inside the @Click trigger made it being called endlessly. + +16-10-2023, Nolok +- Fixed: Memory leaks due to the old CSPtrTypeArray and CSObjArray containers, replaced with new ones using smart pointers as wrappers. +- Fixed: Possible random errors caused by reading some internal data before it was initialized during server startup (CCrypto::client_keys, holding SphereCrypt data, and ThreadHolder, holding threads data). +- Fixed: CSString instances becoming invalid after calling the Clear method. \ No newline at end of file diff --git a/src/CMakeSources.cmake b/src/CMakeSources.cmake index e30c100cf..17be7a262 100644 --- a/src/CMakeSources.cmake +++ b/src/CMakeSources.cmake @@ -255,13 +255,14 @@ src/common/sphere_library/CSTime.cpp src/common/sphere_library/CSTime.h src/common/sphere_library/CSWindow.cpp src/common/sphere_library/CSWindow.h -src/common/sphere_library/container_ops.h +src/common/sphere_library/scontainer_ops.h src/common/sphere_library/smap.h src/common/sphere_library/smutex.h src/common/sphere_library/smutex.cpp src/common/sphere_library/squeues.h src/common/sphere_library/sresetevents.cpp src/common/sphere_library/sresetevents.h +src/common/sphere_library/sptr_containers.h src/common/sphere_library/sstacks.h src/common/sphere_library/sstring.cpp src/common/sphere_library/sstring.h diff --git a/src/common/CException.cpp b/src/common/CException.cpp index d8eaabde9..e23ebb95b 100644 --- a/src/common/CException.cpp +++ b/src/common/CException.cpp @@ -281,8 +281,8 @@ void _cdecl Signal_Terminate(int sig = 0) // If shutdown is initialized } g_Serv.SetExitFlag(SIGABRT); - for (size_t i = 0; i < ThreadHolder::getActiveThreads(); ++i) - ThreadHolder::getThreadAt(i)->terminate(false); + for (size_t i = 0; i < ThreadHolder::get()->getActiveThreads(); ++i) + ThreadHolder::get()->getThreadAt(i)->terminate(false); //exit(EXIT_FAILURE); } diff --git a/src/common/CException.h b/src/common/CException.h index ea344b2ee..4ce8d17d9 100644 --- a/src/common/CException.h +++ b/src/common/CException.h @@ -115,7 +115,7 @@ class CAssert : public CSError #endif // _EXC_CAUGHT -#define _EXC_CAUGHT static_cast(ThreadHolder::current())->exceptionCaught() +#define _EXC_CAUGHT static_cast(ThreadHolder::get()->current())->exceptionCaught() /*--- Main (non SUB) macros ---*/ diff --git a/src/common/CExpression.cpp b/src/common/CExpression.cpp index 89f85b8d1..fcf6eb98c 100644 --- a/src/common/CExpression.cpp +++ b/src/common/CExpression.cpp @@ -48,7 +48,7 @@ dword ahextoi( lpctstr pszStr ) // Convert hex string to integer } else if ( !bHex && ( ch == '.' ) ) { - pszStr++; + ++ pszStr; continue; } else @@ -56,7 +56,7 @@ dword ahextoi( lpctstr pszStr ) // Convert hex string to integer val *= ( bHex ? 0x10 : 10 ); val += ch; - pszStr ++; + ++ pszStr; } return val; } diff --git a/src/common/CPointBase.cpp b/src/common/CPointBase.cpp index cea9a3542..99e1bbd59 100644 --- a/src/common/CPointBase.cpp +++ b/src/common/CPointBase.cpp @@ -1,4 +1,4 @@ -#include "../common/sphere_library/container_ops.h" +#include "../common/sphere_library/scontainer_ops.h" #include "../game/items/CItem.h" #include "../game/CSector.h" #include "../game/CServer.h" diff --git a/src/common/crypto/CCrypto.cpp b/src/common/crypto/CCrypto.cpp index 0a8c7c4cc..ff9a0d377 100644 --- a/src/common/crypto/CCrypto.cpp +++ b/src/common/crypto/CCrypto.cpp @@ -20,7 +20,40 @@ /* Login keys from SphereCrypt.ini */ -std::vector CCrypto::client_keys; +CCryptoKeysHolder* CCryptoKeysHolder::get() noexcept +{ + static CCryptoKeysHolder instance; + return &instance; +} + +void CCryptoKeysHolder::LoadKeyTable(CScript& s) +{ + ADDTOCALLSTACK("CCrypto::LoadKeyTable"); + client_keys.clear(); + + // Always add nocrypt + addNoCryptKey(); + + while (s.ReadKeyParse()) + { + CCryptoClientKey c; + c.m_client = ahextoi(s.GetKey()); + c.m_key_1 = s.GetArgVal(); + c.m_key_2 = s.GetArgVal(); + c.m_EncType = (ENCRYPTION_TYPE)s.GetArgVal(); + client_keys.emplace_back(std::move(c)); + } +} + +void CCryptoKeysHolder::addNoCryptKey(void) +{ + ADDTOCALLSTACK("CCrypto::addNoCryptKey"); + CCryptoClientKey c{}; + c.m_EncType = ENC_NONE; + client_keys.emplace_back(std::move(c)); +} + +// -- void CCrypto::SetClientVersion( dword iVer ) { @@ -87,35 +120,6 @@ ENCRYPTION_TYPE CCrypto::GetEncryptionType() const return m_GameEnc; } -void CCrypto::LoadKeyTable(CScript & s) -{ - ADDTOCALLSTACK("CCrypto::LoadKeyTable"); - client_keys.clear(); - - // Always add nocrypt - addNoCryptKey(); - - while ( s.ReadKeyParse() ) - { - CCryptoClientKey c; - c.m_client = ahextoi( s.GetKey() ); - c.m_key_1 = s.GetArgVal(); - c.m_key_2 = s.GetArgVal(); - c.m_EncType = (ENCRYPTION_TYPE)s.GetArgVal(); - client_keys.emplace_back(c); - } -} - -void CCrypto::addNoCryptKey(void) -{ - ADDTOCALLSTACK("CCrypto::addNoCryptKey"); - CCryptoClientKey c; - c.m_client = 0; - c.m_key_1 = 0; - c.m_key_2 = 0; - c.m_EncType = ENC_NONE; - client_keys.emplace_back(c); -} // --------------------------------------------------------------------------------------------------------------- // =============================================================================================================== @@ -227,9 +231,10 @@ char* CCrypto::WriteClientVer( char * pcStr, uint uiBufLen) const bool CCrypto::SetClientVerEnum( dword iVer, bool bSetEncrypt ) { ADDTOCALLSTACK("CCrypto::SetClientVerEnum"); - for (size_t i = 0; i < client_keys.size(); ++i ) + CCryptoKeysHolder* keys_holder = CCryptoKeysHolder::get(); + for (size_t i = 0; i < keys_holder->client_keys.size(); ++i ) { - CCryptoClientKey & key = client_keys[i]; + CCryptoClientKey & key = keys_holder->client_keys[i]; if ( iVer == key.m_client ) { @@ -244,10 +249,12 @@ bool CCrypto::SetClientVerEnum( dword iVer, bool bSetEncrypt ) bool CCrypto::SetClientVerIndex( size_t iVer, bool bSetEncrypt ) { ADDTOCALLSTACK("CCrypto::SetClientVerIndex"); - if ( iVer >= client_keys.size() ) + CCryptoKeysHolder* keys_holder = CCryptoKeysHolder::get(); + + if ( iVer >= keys_holder->client_keys.size() ) return false; - CCryptoClientKey & key = client_keys[iVer]; + CCryptoClientKey & key = keys_holder->client_keys[iVer]; SetClientVersion(key.m_client); SetMasterKeys(key.m_key_1, key.m_key_2); // Hi - Lo @@ -292,9 +299,11 @@ bool CCrypto::SetClientVer( lpctstr pszVersion ) CCrypto::CCrypto() { + CCryptoKeysHolder* keys_holder = CCryptoKeysHolder::get(); + // Always at least one crypt code, for non encrypted clients! - if ( ! client_keys.size() ) - addNoCryptKey(); + if ( !keys_holder->client_keys.size() ) + keys_holder->addNoCryptKey(); m_fInit = false; m_fRelayPacket = false; @@ -605,7 +614,7 @@ bool CCrypto::LoginCryptStart( dword dwIP, const byte * pEvent, uint inLen ) ASSERT(inLen <= MAX_BUFFER); std::unique_ptr pRaw = std::make_unique(MAX_BUFFER); memcpy(pRaw.get(), pEvent, inLen); - + m_seed = dwIP; SetConnectType( CONNECT_LOGIN ); @@ -615,9 +624,11 @@ bool CCrypto::LoginCryptStart( dword dwIP, const byte * pEvent, uint inLen ) SetClientVerIndex(0); SetCryptMask(tmp_CryptMaskHi, tmp_CryptMaskLo); + CCryptoKeysHolder* keys_holder = CCryptoKeysHolder::get(); + for (uint i = 0, iAccountNameLen = 0;;) { - if ( i >= client_keys.size() ) + if ( i >= keys_holder->client_keys.size() ) { // Unknown client !!! Set as unencrypted and let Sphere do the rest. #ifdef DEBUG_CRYPT_MSGS @@ -746,9 +757,10 @@ bool CCrypto::GameCryptStart( dword dwIP, const byte * pEvent, uint inLen ) const dword tmp_CryptMaskHi = ((( m_seed) ^ 0x43210000) >> 16) | (((~m_seed) ^ 0xabcdffff) & 0xffff0000); SetClientVerIndex(0); + CCryptoKeysHolder* keys_holder = CCryptoKeysHolder::get(); for (size_t i = 0;;) { - if ( i >= client_keys.size() ) + if ( i >= keys_holder->client_keys.size() ) { // Unknown client !!! Set as unencrypted and let Sphere do the rest. #ifdef DEBUG_CRYPT_MSGS @@ -782,7 +794,7 @@ bool CCrypto::GameCryptStart( dword dwIP, const byte * pEvent, uint inLen ) if ( pRaw[34] == 0x00 && pRaw[64] == 0x00) { bOut = true; // Ok the new detected encryption is ok (legit post-login packet: 0x91) - SetCryptMask(tmp_CryptMaskHi, tmp_CryptMaskLo); + SetCryptMask(tmp_CryptMaskHi, tmp_CryptMaskLo); break; } } diff --git a/src/common/crypto/CCrypto.h b/src/common/crypto/CCrypto.h index 6b010d953..042abc3d0 100644 --- a/src/common/crypto/CCrypto.h +++ b/src/common/crypto/CCrypto.h @@ -81,15 +81,25 @@ struct CCryptoClientKey // =============================================================================================================== -struct CCrypto +struct CCryptoKeysHolder { -public: + static CCryptoKeysHolder* get() noexcept; + union CCryptoKey // For internal encryption calculations, it has nothing to do with SphereCrypt.ini { - #define CRYPT_GAMESEED_LENGTH 8 +#define CRYPT_GAMESEED_LENGTH 8 byte u_cKey[CRYPT_GAMESEED_LENGTH]; dword u_iKey[2]; }; + + std::vector client_keys; + + void LoadKeyTable(CScript& s); + void addNoCryptKey(void); +}; + +struct CCrypto +{ private: bool m_fInit; bool m_fRelayPacket; @@ -109,12 +119,6 @@ struct CCrypto //static const word packet_size[0xde]; -public: - static std::vector client_keys; - - static void LoadKeyTable(CScript & s); - static void addNoCryptKey(void); - // --------------- Generic ----------------------------------- //static int GetPacketSize(byte packet); // --------------- EOF Generic ------------------------------- @@ -150,11 +154,11 @@ struct CCrypto int m_gameBlockPos; // 0-7 size_t m_gameStreamPos; // use this to track the 21K move to the new Blowfish m_gameTable. private: - CCrypto::CCryptoKey m_Key; + CCryptoKeysHolder::CCryptoKey m_Key; private: void InitSeed( int iTable ); static void InitTables(); - static void PrepareKey( CCrypto::CCryptoKey & key, int iTable ); + static void PrepareKey(CCryptoKeysHolder::CCryptoKey & key, int iTable ); bool DecryptBlowFish( byte * pOutput, const byte * pInput, size_t outLen, size_t inLen ); byte DecryptBFByte( byte bEnc ); void InitBlowFish(); diff --git a/src/common/crypto/CCryptoBlowFish.cpp b/src/common/crypto/CCryptoBlowFish.cpp index 26faefe4c..802cce0fd 100644 --- a/src/common/crypto/CCryptoBlowFish.cpp +++ b/src/common/crypto/CCryptoBlowFish.cpp @@ -7,7 +7,7 @@ dword sm_dwCodingData[CRYPT_GAMEKEY_COUNT][18+1024]; // to be filled by InitTabl bool CCrypto::sm_fTablesReady = false; -void CCrypto::PrepareKey( CCrypto::CCryptoKey & key, int iTable ) // static +void CCrypto::PrepareKey(CCryptoKeysHolder::CCryptoKey & key, int iTable ) // static { ADDTOCALLSTACK("CCrypto::PrepareKey"); const dword *pCodes = sm_dwCodingData[iTable]; @@ -42,7 +42,7 @@ void CCrypto::InitTables() // static sm_dwCodingData[i][j] ^= code[j%3]; } - CCrypto::CCryptoKey tmpKey; + CCryptoKeysHolder::CCryptoKey tmpKey; tmpKey.u_iKey[0] = tmpKey.u_iKey[1] = 0; for(j=0; j<0x412; j+=2) diff --git a/src/common/resource/CResourceBase.cpp b/src/common/resource/CResourceBase.cpp index 487fb6eca..06caa74ab 100644 --- a/src/common/resource/CResourceBase.cpp +++ b/src/common/resource/CResourceBase.cpp @@ -383,24 +383,38 @@ int CResourceBase::ResourceGetIndexType( RES_TYPE restype, lpctstr pszName, word return rid.GetResIndex(); } -CResourceDef * CResourceBase::ResourceGetDef(const CResourceID& rid) const +std::weak_ptr CResourceBase::ResourceGetDefRef(const CResourceID& rid) const { - ADDTOCALLSTACK("CResourceBase::ResourceGetDef"); + ADDTOCALLSTACK("CResourceBase::ResourceGetDefRef"); if ( ! rid.IsValidResource() ) - return nullptr; + return {}; size_t index = m_ResHash.FindKey( rid ); if ( index == SCONT_BADINDEX ) - return nullptr; - return m_ResHash.GetAt( rid, index ); + return {}; + return m_ResHash.GetWeakPtrAt( rid, index ).lock(); } -CScriptObj * CResourceBase::ResourceGetDefByName( RES_TYPE restype, lpctstr pszName, word wPage ) +std::weak_ptr CResourceBase::ResourceGetDefRefByName( RES_TYPE restype, lpctstr pszName, word wPage ) { - ADDTOCALLSTACK("CResourceBase::ResourceGetDefByName"); + ADDTOCALLSTACK("CResourceBase::ResourceGetDefRefByName"); // resolve a name to the actual resource def. - CResourceID res = ResourceGetID(restype, pszName); + CResourceID res = ResourceGetID(restype, pszName, wPage); res.m_wPage = wPage ? wPage : RES_PAGE_ANY; // Create a CResourceID with page == RES_PAGE_ANY: search independently from the page - return ResourceGetDef(res); + return ResourceGetDefRef(res); +} + +CResourceDef* CResourceBase::ResourceGetDef(const CResourceID& rid) const +{ + ADDTOCALLSTACK("CResourceBase::ResourceGetDef"); + std::shared_ptr ret = ResourceGetDefRef(rid).lock(); + return ret ? ret.get() : nullptr; +} + +CResourceDef* CResourceBase::ResourceGetDefByName(RES_TYPE restype, lpctstr pszName, word wPage) +{ + ADDTOCALLSTACK("CResourceBase::ResourceGetDefByName"); + std::shared_ptr ret = ResourceGetDefRefByName(restype, pszName, wPage).lock(); + return ret ? ret.get() : nullptr; } //******************************************************* @@ -412,8 +426,13 @@ bool CResourceBase::ResourceLock( CResourceLock & s, const CResourceID& rid ) // Lock a referenced resource object. if ( ! rid.IsValidUID() ) return false; - CResourceLink * pResourceLink = dynamic_cast ( ResourceGetDef( rid )); - if ( pResourceLink ) - return pResourceLink->ResourceLock(s); + std::shared_ptr pResourceDefRef = ResourceGetDefRef(rid).lock(); + if (pResourceDefRef) + { + CResourceLink* pResourceLink = dynamic_cast (pResourceDefRef.get()); + if (pResourceLink) + return pResourceLink->ResourceLock(s); + } + return false; } diff --git a/src/common/resource/CResourceBase.h b/src/common/resource/CResourceBase.h index 8d7eaa397..e51d0fd0e 100644 --- a/src/common/resource/CResourceBase.h +++ b/src/common/resource/CResourceBase.h @@ -44,7 +44,6 @@ class CResourceBase : public CScriptObj CResourceID ResourceGetID( RES_TYPE restype, lpctstr ptcName, word wPage = 0 ); CResourceID ResourceGetIDType( RES_TYPE restype, lpctstr pszName, word wPage = 0 ); int ResourceGetIndexType( RES_TYPE restype, lpctstr pszName, word wPage = 0 ); - CScriptObj * ResourceGetDefByName( RES_TYPE restype, lpctstr pszName, word wPage = 0 ); bool ResourceLock( CResourceLock & s, const CResourceID& rid ); bool ResourceLock( CResourceLock & s, RES_TYPE restype, lpctstr pszName ) { @@ -54,7 +53,10 @@ class CResourceBase : public CScriptObj CResourceScript * FindResourceFile( lpctstr pszTitle ); CResourceScript * LoadResourcesAdd( lpctstr pszNewName ); - virtual CResourceDef * ResourceGetDef( const CResourceID& rid ) const; + std::weak_ptr ResourceGetDefRef(const CResourceID& rid) const; + CResourceDef * ResourceGetDef( const CResourceID& rid ) const; + std::weak_ptr ResourceGetDefRefByName(RES_TYPE restype, lpctstr pszName, word wPage = 0); + CResourceDef* ResourceGetDefByName(RES_TYPE restype, lpctstr pszName, word wPage = 0); virtual bool OpenResourceFind( CScript &s, lpctstr pszFilename, bool fCritical = true ); virtual bool LoadResourceSection( CScript * pScript ) = 0; diff --git a/src/common/resource/CResourceHash.cpp b/src/common/resource/CResourceHash.cpp index db9ced0aa..b3f6acf5e 100644 --- a/src/common/resource/CResourceHash.cpp +++ b/src/common/resource/CResourceHash.cpp @@ -6,7 +6,7 @@ #include "CResourceDef.h" #include "CResourceHash.h" -bool CResourceHashArraySorter::operator()(const CResourceDef* pObjStored, const CResourceDef* pObj) const +bool CResourceHashArraySorter::operator()(std::shared_ptr const& pObjStored, std::shared_ptr const& pObj) const { // < : true // >= : false @@ -24,7 +24,7 @@ bool CResourceHashArraySorter::operator()(const CResourceDef* pObjStored, const return true; } -int CResourceHashArray::_compare(const CResourceDef* pObjStored, CResourceID const& rid) // static +int CResourceHashArray::_compare(std::shared_ptr const& pObjStored, CResourceID const& rid) // static { ASSERT( pObjStored ); CResourceID const& ridStored = pObjStored->GetResourceID(); @@ -56,7 +56,7 @@ void CResourceHash::AddSortKey(CResourceID const& rid, CResourceDef* pNew) void CResourceHash::SetAt(CResourceID const& rid, size_t index, CResourceDef* pNew) { ASSERT(rid.GetResPage() <= RES_PAGE_MAX); // RES_PAGE_ANY can be used only for search, you can't insert a rid with this special page - m_Array[GetHashArray(rid)][index] = pNew; + m_Array[GetHashArray(rid)][index].reset(pNew); } /* diff --git a/src/common/resource/CResourceHash.h b/src/common/resource/CResourceHash.h index caca57ae4..24828076f 100644 --- a/src/common/resource/CResourceHash.h +++ b/src/common/resource/CResourceHash.h @@ -7,6 +7,7 @@ #define _INC_CRESOURCEHASH_H #include "../sphere_library/CSObjSortArray.h" +#include "../sphere_library/sptr_containers.h" #include "CResourceID.h" class CResourceDef; @@ -14,11 +15,11 @@ class CResourceDef; struct CResourceHashArraySorter { - bool operator()(const CResourceDef* pObjStored, const CResourceDef* pObj) const; + bool operator()(std::shared_ptr const& pObjStored, std::shared_ptr const& pObj) const; }; -class CResourceHashArray : public CSSortedVector< CResourceDef*, CResourceHashArraySorter > +class CResourceHashArray : public CSSharedPtrSortedVector { - static int _compare(const CResourceDef* pObjStored, CResourceID const& rid); + static int _compare(std::shared_ptr const& pObjStored, CResourceID const& rid); public: // This list OWNS the CResourceDef and CResourceLink objects. @@ -42,7 +43,7 @@ struct CResourceHash CResourceHash& operator=(const CResourceHash&) = delete; private: - inline int GetHashArray(const CResourceID& rid) const + inline uint GetHashArray(const CResourceID& rid) const { return (rid.GetResIndex() & 0x0F); } @@ -52,9 +53,13 @@ struct CResourceHash { return m_Array[GetHashArray(rid)].find_sorted(rid); } - inline CResourceDef* GetAt(const CResourceID& rid, size_t index) const + inline std::weak_ptr GetWeakPtrAt(const CResourceID& rid, size_t index) const { - return m_Array[GetHashArray(rid)][index]; + return std::weak_ptr(m_Array[GetHashArray(rid)][index]); + } + inline CResourceDef* GetBarePtrAt(const CResourceID& rid, size_t index) const + { + return m_Array[GetHashArray(rid)][index].get(); } void AddSortKey(CResourceID const& rid, CResourceDef* pNew); diff --git a/src/common/resource/CResourceID.cpp b/src/common/resource/CResourceID.cpp index 746783d95..acd8d4f03 100644 --- a/src/common/resource/CResourceID.cpp +++ b/src/common/resource/CResourceID.cpp @@ -11,13 +11,13 @@ static constexpr lpctstr _ptcWarnInvalidResource = "Expected a valid ResourceID, CResourceIDBase::CResourceIDBase(RES_TYPE restype) // explicit { // single instance type. - ASSERT(restype <= RES_TYPE_MASK); + ASSERT(restype < RES_QTY); m_dwInternalVal = UID_F_RESOURCE | (restype << RES_TYPE_SHIFT); } CResourceIDBase::CResourceIDBase(RES_TYPE restype, int iIndex) // explicit { - ASSERT(restype <= RES_TYPE_MASK); + ASSERT(restype < RES_QTY); m_dwInternalVal = UID_F_RESOURCE | (restype << RES_TYPE_SHIFT) | (iIndex & RES_INDEX_MASK); } diff --git a/src/common/resource/CResourceQty.cpp b/src/common/resource/CResourceQty.cpp index a7f038209..5d4c18b44 100644 --- a/src/common/resource/CResourceQty.cpp +++ b/src/common/resource/CResourceQty.cpp @@ -37,7 +37,7 @@ size_t CResourceQty::WriteNameSingle( tchar * pszArgs, int iQty ) const if ( pItemBase ) return( Str_CopyLen( pszArgs, pItemBase->GetNamePluralize(pItemBase->GetTypeName(),(( iQty > 1 ) ? true : false))) ); } - const CScriptObj * pResourceDef = g_Cfg.ResourceGetDef( m_rid ); + auto pResourceDef = static_cast(g_Cfg.RegisteredResourceGetDef(m_rid)); if ( pResourceDef != nullptr ) return( Str_CopyLen( pszArgs, pResourceDef->GetName()) ); else diff --git a/src/common/resource/CResourceRef.cpp b/src/common/resource/CResourceRef.cpp index adf66eba6..4e65a7519 100644 --- a/src/common/resource/CResourceRef.cpp +++ b/src/common/resource/CResourceRef.cpp @@ -83,6 +83,7 @@ bool CResourceRefArray::r_LoadVal( CScript & s, RES_TYPE restype ) int iArgCount = Str_ParseCmds( pszCmd, ppBlocks, ARRAY_COUNT(ppBlocks)); for ( int i = 0; i < iArgCount; ++i ) { + std::shared_ptr pResourceDefRef; CResourceLink* pResourceLink = nullptr; pszCmd = ppBlocks[i]; diff --git a/src/common/resource/sections/CItemTypeDef.cpp b/src/common/resource/sections/CItemTypeDef.cpp index 23ebbadcc..c9312d30c 100644 --- a/src/common/resource/sections/CItemTypeDef.cpp +++ b/src/common/resource/sections/CItemTypeDef.cpp @@ -1,3 +1,4 @@ +#include "../../../game/CServerConfig.h" #include "../../../game/CWorld.h" #include "../../../sphere/threads.h" #include "../../CException.h" @@ -51,9 +52,12 @@ bool CItemTypeDef::r_LoadVal( CScript & s ) iLo = iTmp; } + // Get the weak ptr from reshash + std::weak_ptr def_registered = g_Cfg.RegisteredResourceGetDefRef(GetResourceID()); + ASSERT(!def_registered.expired()); for (llong i = iLo; i <= iHi; ++i ) { - g_World.m_TileTypes.assign_at_grow(size_t(i), this); + g_World.m_TileTypes.emplace_index_grow(i, def_registered); } return true; } diff --git a/src/common/resource/sections/CItemTypeDef.h b/src/common/resource/sections/CItemTypeDef.h index 8a2820ed1..a29e5ed85 100644 --- a/src/common/resource/sections/CItemTypeDef.h +++ b/src/common/resource/sections/CItemTypeDef.h @@ -17,9 +17,9 @@ class CItemTypeDef : public CResourceLink { } -private: - CItemTypeDef(const CItemTypeDef& copy); - CItemTypeDef& operator=(const CItemTypeDef& other); + //CItemTypeDef(CItemTypeDef&&) = default; + CItemTypeDef(const CItemTypeDef& copy) = delete; + CItemTypeDef& operator=(const CItemTypeDef& other) = delete; public: virtual bool r_LoadVal( CScript & s ) override; diff --git a/src/common/resource/sections/CWebPageDef.cpp b/src/common/resource/sections/CWebPageDef.cpp index 5ebe5ab98..10d76e3e2 100644 --- a/src/common/resource/sections/CWebPageDef.cpp +++ b/src/common/resource/sections/CWebPageDef.cpp @@ -231,7 +231,7 @@ bool CWebPageDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on for ( size_t i = 0; i < g_World.m_Stones.size(); ++i ) { - CItemStone * pStone = g_World.m_Stones[i]; + CItemStone * pStone = g_World.m_Stones[i].get(); if ( !pStone || !pStone->IsType(needtype) ) continue; diff --git a/src/common/sphere_library/CSMemBlock.cpp b/src/common/sphere_library/CSMemBlock.cpp index 0469c3814..49ed0b938 100644 --- a/src/common/sphere_library/CSMemBlock.cpp +++ b/src/common/sphere_library/CSMemBlock.cpp @@ -18,11 +18,12 @@ CSMemBlock::~CSMemBlock() void CSMemBlock::Alloc( size_t uiSize ) { Free(); + ASSERT(m_pData == nullptr); if ( uiSize > 0 ) m_pData = AllocBase(uiSize); } -byte * CSMemBlock::AllocBase( size_t uiSize ) +byte * CSMemBlock::AllocBase( size_t uiSize ) // Static { ASSERT(uiSize > 0); byte * pData = new byte[ uiSize ]; diff --git a/src/common/sphere_library/CSMemBlock.h b/src/common/sphere_library/CSMemBlock.h index 472335be8..3ba78f865 100644 --- a/src/common/sphere_library/CSMemBlock.h +++ b/src/common/sphere_library/CSMemBlock.h @@ -43,7 +43,7 @@ class CSMemBlock * @param dwSize size to alloc. * @return pointer to the allocated data. */ - byte * AllocBase( size_t uiSize ); + static byte * AllocBase( size_t uiSize ); public: /** * @brief Clear internal data pointer if it is not nullptr. diff --git a/src/common/sphere_library/CSObjArray.h b/src/common/sphere_library/CSObjArray.h index 83f704261..d5a2bf5c1 100644 --- a/src/common/sphere_library/CSObjArray.h +++ b/src/common/sphere_library/CSObjArray.h @@ -24,7 +24,7 @@ class CSObjArray : public CSPtrTypeArray */ ///@{ public: - CSObjArray() : _fBaseDestructorShouldDeleteElements(false) { + CSObjArray() : _fBaseDestructorShouldDeleteElements(true) { } virtual ~CSObjArray() { DeleteElements(); diff --git a/src/common/sphere_library/CSSortedVector.h b/src/common/sphere_library/CSSortedVector.h index ebc3720ea..d6c9889fe 100644 --- a/src/common/sphere_library/CSSortedVector.h +++ b/src/common/sphere_library/CSSortedVector.h @@ -11,9 +11,10 @@ template > class CSSortedVector : public std::vector<_Type> { public: - using iterator = typename std::vector<_Type>::iterator; - using const_iterator = typename std::vector<_Type>::const_iterator; - using size_type = typename std::vector<_Type>::size_type; + using base_type = typename std::vector<_Type>; + using iterator = typename base_type::iterator; + using const_iterator = typename base_type::const_iterator; + using size_type = typename base_type::size_type; private: const _Comp _comparatorObj; @@ -53,19 +54,28 @@ class CSSortedVector : public std::vector<_Type> { //_Type * _obj = new _Type(std::forward<_ValType>(value)...); _Type _obj(std::forward<_ValType>(value)...); - const size_t _mySize = this->size(); - const size_t _pos = (_mySize == 0) ? 0 : lower_element(_mySize, this->data(), _obj); - return std::vector<_Type>::emplace(this->begin() + _pos, std::move(_obj)); + const size_t _mySize = base_type::size(); + const size_t _pos = (_mySize == 0) ? 0 : this->lower_element(_mySize, base_type::data(), _obj); + return base_type::emplace(base_type::begin() + _pos, std::move(_obj)); } inline iterator insert(_Type const& value) { - return emplace(value); + return this->emplace(value); } - inline iterator insert( _Type&& value) { - return emplace(std::move(value)); + inline iterator insert(_Type&& value) { + return this->emplace(std::move(value)); } //iterator insert(const size_Typepe _Count, const _Typepe& value) = delete; + inline void remove(const size_t index) { + base_type::erase(base_type::begin() + index); + } + void remove_ptr(_Type* elem) { + const size_t uiFoundIndex = this->find(elem); + if (uiFoundIndex != SCONT_BADINDEX) + this->remove(uiFoundIndex); + } + size_t find(_Type const& value) const noexcept; @@ -128,7 +138,7 @@ size_t CSSortedVector<_Type, _Comp>::binary_search_predicate(size_t _size, _ValT return 0; */ - const _Type* const _dataptr = this->data(); + const _Type* const _dataptr = base_type::data(); size_t _lo = 0; while (_lo < _size) { @@ -153,11 +163,11 @@ size_t CSSortedVector<_Type, _Comp>::binary_search_predicate(size_t _size, _ValT template size_t CSSortedVector<_Type, _Comp>::find(_Type const& value) const noexcept { - const size_t _mySize = this->size(); + const size_t _mySize = base_type::size(); if (_mySize == 0) { return SCONT_BADINDEX; } - const _Type* const _dataptr = this->data(); + const _Type* const _dataptr = base_type::data(); size_t _idx = this->lower_element(_mySize, _dataptr, value); if (_idx == _mySize) return SCONT_BADINDEX; @@ -168,7 +178,7 @@ template template size_t CSSortedVector<_Type, _Comp>::find_predicate(_ValType const& value, _Pred&& predicate) const noexcept { - const size_t _mySize = this->size(); + const size_t _mySize = base_type::size(); if (_mySize == 0) { return SCONT_BADINDEX; } diff --git a/src/common/sphere_library/CSString.cpp b/src/common/sphere_library/CSString.cpp index 29919df4c..d8900992a 100644 --- a/src/common/sphere_library/CSString.cpp +++ b/src/common/sphere_library/CSString.cpp @@ -47,7 +47,8 @@ // CSString:: Constructors -CSString::CSString(bool fDefaultInit) +CSString::CSString(bool fDefaultInit) : + m_pchData(nullptr) { #ifdef DEBUG_STRINGS ++gAmount; @@ -67,19 +68,22 @@ CSString::CSString(bool fDefaultInit) } } -CSString::CSString(lpctstr pStr) +CSString::CSString(lpctstr pStr) : + m_pchData(nullptr) { Init(); Copy(pStr); } -CSString::CSString(lpctstr pStr, int iLen) +CSString::CSString(lpctstr pStr, int iLen) : + m_pchData(nullptr) { Init(); CopyLen(pStr, iLen); } -CSString::CSString(const CSString& s) +CSString::CSString(const CSString& s) : + m_pchData(nullptr) { Init(); Copy(s.GetBuffer()); @@ -94,7 +98,8 @@ void CSString::Init() gMemAmount += m_iMaxLength; #endif m_iLength = 0; - m_pchData = new tchar[size_t(m_iMaxLength + 1)]; + if (m_pchData == nullptr) + m_pchData = new tchar[size_t(m_iMaxLength + 1)]; m_pchData[m_iLength] = '\0'; } diff --git a/src/common/sphere_library/container_ops.h b/src/common/sphere_library/scontainer_ops.h similarity index 100% rename from src/common/sphere_library/container_ops.h rename to src/common/sphere_library/scontainer_ops.h diff --git a/src/common/sphere_library/sptr_containers.h b/src/common/sphere_library/sptr_containers.h new file mode 100644 index 000000000..74f03f10c --- /dev/null +++ b/src/common/sphere_library/sptr_containers.h @@ -0,0 +1,189 @@ +#ifndef _SPTR_CONTAINERS_H +#define _SPTR_CONTAINERS_H + +#include "CSSortedVector.h" +#include +#include + + +//-- Base types for a standard vector or sorted vector of smart pointers +template +class _CSPtrVectorBase : public std::vector<_PtrWrapperType> +{ +public: + using _base_type = std::vector<_PtrWrapperType>; + using iterator = typename _base_type::iterator; + + inline void remove(const size_t index) { + _base_type::erase(_base_type::begin() + index); + } + + void remove(_Type* elem) { + size_t idx = 0; + for (_PtrWrapperType const& ptr : *this) { + if (ptr.get() == elem) { + remove(idx); + return; + } + ++idx; + } + } + + inline bool valid_index(size_t index) const noexcept { + if constexpr (std::is_same_v<_PtrWrapperType, std::weak_ptr<_Type>>) { + return (index < _base_type::size()) && !(_base_type::operator[](index).expired()); + } + else { + return (index < _base_type::size()) && static_cast(_base_type::operator[](index)); + } + } +}; + +template > +class _CSPtrSortedVectorBase : public CSSortedVector<_PtrWrapperType, _Comp> +{ +public: + using _base_type = CSSortedVector<_PtrWrapperType>; + using iterator = typename _base_type::iterator; + + inline bool valid_index(size_t index) const noexcept { + if constexpr (std::is_same_v<_PtrWrapperType, std::weak_ptr<_Type>>) { + return (index < _base_type::size()) && !(_base_type::operator[](index).expired()); + } + else { + return (index < _base_type::size()) && static_cast(_base_type::operator[](index)); + } + } +}; + + +// -- Vectors of pointers, wrapped in unique pointers + +template +class CSUniquePtrVector : public _CSPtrVectorBase<_Type, std::unique_ptr<_Type>> +{ +public: + template > // Gets both bare pointer and shared_ptr + void emplace_index_grow(size_t index, _PtrType value) { + if (index >= this->size()) { + this->resize(index + 1); // The capacity will be even greater, since it calls vector::resize + } + if (!value || value.get() == nullptr) + this->operator[](index).reset(); + else + this->operator[](index) = value; + } + + //template + inline void emplace_index_grow(size_t index, std::nullptr_t) { + this->emplace_index_grow(index, std::unique_ptr<_Type>()); + } + + //template <> + void emplace_index_grow(size_t, _Type*) = delete; + + /* + template + void emplace_index_grow(size_t index, _ArgType&&... value) { + if (index >= this->size()) { + this->resize(index + 1); // The capacity will be even greater, since it calls vector::resize + } + this->operator[](index) = std::move(std::make_unique, _ArgType&&...> + (std::forward<_ArgType>(value)...)); + } + */ + + /* + // An old attempt with good ideas + template + void emplace_index_grow(size_t index, _ArgType&&... value) { + if (index >= this->size()) { + this->resize(index); // The capacity will be even greater, since it calls vector::resize + } + if constexpr (sizeof...(value) == 1) { + using _FirstPackedType = std::tuple_element_t<0, std::tuple<_ArgType...>>; + if constexpr (std::is_pointer_v>) { + auto _FirstPackedValue = std::get<0>(std::tie(value...)); + this->operator[](index).reset(std::forward<_Type*>(_FirstPackedValue)); + } + } + else { + this->operator[](index) = std::move(std::make_unique<_Type>(std::forward<_ArgType>(value)...)); + } + } + */ +}; +template > +class CSUniquePtrSortedVector : public _CSPtrSortedVectorBase<_Type, std::unique_ptr<_Type>, _Comp> +{}; + + +// -- Vectors of pointers, wrapped in shared pointers +template +class CSSharedPtrVector : public _CSPtrVectorBase<_Type, std::shared_ptr<_Type>> +{ +public: + template > // Gets both bare pointer and shared_ptr + void emplace_index_grow(size_t index, _PtrType value) { + if (index >= this->size()) { + this->resize(index + 1); // The capacity will be even greater, since it calls vector::resize + } + if (!value || value.get() == nullptr) + this->operator[](index).reset(); + else + this->operator[](index) = value; + } + + //emplate + inline void emplace_index_grow(size_t index, std::nullptr_t) { + this->emplace_index_grow(index, std::shared_ptr<_Type>()); + } + + //template <> + void emplace_index_grow(size_t, _Type*) = delete; + + /* + template + void emplace_index_grow(size_t index, _ArgType&&... value) { + if (index >= this->size()) { + this->resize(index+1); // The capacity will be even greater, since it calls vector::resize + } + this->operator[](index) = std::move(std::make_shared, _ArgType&&...> + (std::forward<_ArgType>(value)...)); + }*/ +}; +template > +class CSSharedPtrSortedVector : public _CSPtrSortedVectorBase<_Type, std::shared_ptr<_Type>, _Comp> +{}; + + +// -- Vectors of pointers, wrapped in weak pointers + +template +class CSWeakPtrVector : public _CSPtrVectorBase<_Type, std::weak_ptr<_Type>> +{ +public: + template + void emplace_index_grow(size_t index, _ArgType&& value) { + if (index >= this->size()) { + this->resize(index + 1); // The capacity will be even greater, since it calls vector::resize + } + this->operator[](index) = std::forward<_ArgType>(value); + } + + //template + void emplace_index_grow(size_t index, std::nullptr_t) { + if (index >= this->size()) { + this->resize(index); // The capacity will be even greater, since it calls vector::resize + } + else { + this->operator[](index).reset(); + } + } +}; +template > +class CSWeakPtrSortedVector : public _CSPtrSortedVectorBase<_Type, std::weak_ptr<_Type>, _Comp> +{}; + + +#endif // !_SPTR_CONTAINERS_H diff --git a/src/common/sphere_library/sstring.cpp b/src/common/sphere_library/sstring.cpp index 86e55f7fc..e5fbc112c 100644 --- a/src/common/sphere_library/sstring.cpp +++ b/src/common/sphere_library/sstring.cpp @@ -10,7 +10,7 @@ #include #pragma warning( push ) #pragma warning ( disable : ALL_CODE_ANALYSIS_WARNINGS ) -#elif defined(__GNUC__) +#elif defined(__GNUC__) && !defined(__clang__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" #endif diff --git a/src/common/sphere_library/sstring.h b/src/common/sphere_library/sstring.h index 675e2a28d..20746430d 100644 --- a/src/common/sphere_library/sstring.h +++ b/src/common/sphere_library/sstring.h @@ -371,8 +371,8 @@ tchar * Str_UnQuote(tchar * pStr); //-- // extern tchar * Str_GetTemporary(int amount = 1); -#define Str_GetTemp static_cast(ThreadHolder::current())->allocateBuffer -#define Str_GetWTemp static_cast(ThreadHolder::current())->allocateWBuffer +#define Str_GetTemp static_cast(ThreadHolder::get()->current())->allocateBuffer +#define Str_GetWTemp static_cast(ThreadHolder::get()->current())->allocateWBuffer #define STR_TEMPLENGTH (size_t)(THREAD_STRING_LENGTH) //-- diff --git a/src/common/sphere_library/sstringobjs.cpp b/src/common/sphere_library/sstringobjs.cpp index f9c9c5b03..29633fc6e 100644 --- a/src/common/sphere_library/sstringobjs.cpp +++ b/src/common/sphere_library/sstringobjs.cpp @@ -170,7 +170,7 @@ char TemporaryString::m_tempStrings[MAX_TEMP_LINES_NO_CONTEXT][THREAD_STRING_LEN TemporaryString::TemporaryString() { - AbstractSphereThread *current = static_cast (ThreadHolder::current()); + AbstractSphereThread *current = static_cast (ThreadHolder::get()->current()); if ( current != nullptr ) { // allocate from thread context diff --git a/src/game/CComponent.cpp b/src/game/CComponent.cpp index a84a44845..a6f9e1b91 100644 --- a/src/game/CComponent.cpp +++ b/src/game/CComponent.cpp @@ -2,9 +2,9 @@ #include "CComponent.h" #include "CObjBase.h" -CComponent::CComponent(COMP_TYPE type) +CComponent::CComponent(COMP_TYPE type) : + _iType(type) { - _iType = type; } COMP_TYPE CComponent::GetType() const diff --git a/src/game/CServer.cpp b/src/game/CServer.cpp index 3a7fb94f0..02dcc0fc0 100644 --- a/src/game/CServer.cpp +++ b/src/game/CServer.cpp @@ -666,16 +666,16 @@ bool CServer::OnConsoleCmd( CSString & sText, CTextConsole * pSrc ) { if (pSrc != this) { - pSrc->SysMessagef("Current active threads: %" PRIuSIZE_T ".\n", ThreadHolder::getActiveThreads()); + pSrc->SysMessagef("Current active threads: %" PRIuSIZE_T ".\n", ThreadHolder::get()->getActiveThreads()); } else { - g_Log.Event(LOGL_EVENT, "Current active threads: %" PRIuSIZE_T ".\n", ThreadHolder::getActiveThreads()); + g_Log.Event(LOGL_EVENT, "Current active threads: %" PRIuSIZE_T ".\n", ThreadHolder::get()->getActiveThreads()); } - size_t iThreadCount = ThreadHolder::getActiveThreads(); + size_t iThreadCount = ThreadHolder::get()->getActiveThreads(); for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads ) { - IThread * thrCurrent = ThreadHolder::getThreadAt(iThreads); + IThread * thrCurrent = ThreadHolder::get()->getThreadAt(iThreads); if (thrCurrent != nullptr) { pSrc->SysMessagef("%" PRIuSIZE_T " - Id: %lu, Priority: %d, Name: %s.\n", @@ -1059,10 +1059,10 @@ void CServer::ProfileDump( CTextConsole * pSrc, bool bDump ) ftDump->Printf("Profiles %s: (%d sec total)\n", CurrentProfileData.IsActive() ? "ON" : "OFF", CurrentProfileData.GetActiveWindow()); } - size_t iThreadCount = ThreadHolder::getActiveThreads(); + size_t iThreadCount = ThreadHolder::get()->getActiveThreads(); for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads) { - IThread* thrCurrent = ThreadHolder::getThreadAt(iThreads); + IThread* thrCurrent = ThreadHolder::get()->getThreadAt(iThreads); if (thrCurrent == nullptr) continue; diff --git a/src/game/CServerConfig.cpp b/src/game/CServerConfig.cpp index 936a0abf7..819bd3780 100644 --- a/src/game/CServerConfig.cpp +++ b/src/game/CServerConfig.cpp @@ -324,7 +324,7 @@ CServerConfig::~CServerConfig() { for ( size_t j = 0; j < m_ResHash.m_Array[i].size(); ++j ) { - CResourceDef* pResDef = m_ResHash.m_Array[i][j]; + CResourceDef* pResDef = m_ResHash.m_Array[i][j].get(); if ( pResDef != nullptr ) pResDef->UnLink(); } @@ -400,10 +400,10 @@ bool CServerConfig::r_GetRef( lpctstr & ptcKey, CScriptObj * & pRef ) { ++ptcKey; size_t uiOrder = Exp_GetSTVal( ptcKey ); - if ( !m_SpellDefs_Sorted.IsValidIndex( uiOrder ) ) + if ( !m_SpellDefs_Sorted.valid_index( uiOrder ) ) pRef = nullptr; else - pRef = m_SpellDefs_Sorted[uiOrder]; + pRef = m_SpellDefs_Sorted[uiOrder].lock().get(); } else { @@ -411,7 +411,7 @@ bool CServerConfig::r_GetRef( lpctstr & ptcKey, CScriptObj * & pRef ) // check the found resource type matches what we searched for if ( rid.GetResType() == iResType ) - pRef = ResourceGetDef( rid ); + pRef = RegisteredResourceGetDef( rid ); } if ( pszSep != nullptr ) @@ -1264,10 +1264,10 @@ bool CServerConfig::r_LoadVal( CScript &s ) case RC_PROFILE: { int seconds = s.GetArgVal(); - size_t threadCount = ThreadHolder::getActiveThreads(); + size_t threadCount = ThreadHolder::get()->getActiveThreads(); for (size_t j = 0; j < threadCount; ++j) { - AbstractSphereThread* thread = static_cast(ThreadHolder::getThreadAt(j)); + AbstractSphereThread* thread = static_cast(ThreadHolder::get()->getThreadAt(j)); if (thread != nullptr) thread->m_profile.SetActive(seconds); } @@ -1429,9 +1429,9 @@ const CSpellDef * CServerConfig::GetSpellDef( SPELL_TYPE index ) const if (index <= SPELL_NONE) return nullptr; const size_t uiIndex = (size_t)index; - if (!m_SpellDefs.IsValidIndex(uiIndex)) + if (!m_SpellDefs.valid_index(uiIndex)) return nullptr; - return m_SpellDefs[uiIndex]; + return m_SpellDefs[uiIndex].get(); } CSpellDef * CServerConfig::GetSpellDef( SPELL_TYPE index ) @@ -1440,9 +1440,9 @@ CSpellDef * CServerConfig::GetSpellDef( SPELL_TYPE index ) if (index <= SPELL_NONE) return nullptr; const size_t uiIndex = (size_t)index; - if (!m_SpellDefs.IsValidIndex(uiIndex)) + if (!m_SpellDefs.valid_index(uiIndex)) return nullptr; - return m_SpellDefs[uiIndex]; + return m_SpellDefs[uiIndex].get(); } lpctstr CServerConfig::GetSkillKey( SKILL_TYPE index ) const @@ -1451,7 +1451,7 @@ lpctstr CServerConfig::GetSkillKey( SKILL_TYPE index ) const if (index < 0) return nullptr; const size_t uiIndex = (size_t)index; - if (!m_SkillIndexDefs.IsValidIndex(uiIndex)) + if (!m_SkillIndexDefs.valid_index(uiIndex)) return nullptr; return m_SkillIndexDefs[uiIndex]->GetKey(); } @@ -1461,9 +1461,9 @@ const CSkillDef* CServerConfig::GetSkillDef( SKILL_TYPE index ) const if (index < 0) return nullptr; const size_t uiIndex = (size_t)index; - if (!m_SkillIndexDefs.IsValidIndex(uiIndex) ) + if (!m_SkillIndexDefs.valid_index(uiIndex) ) return nullptr; - return m_SkillIndexDefs[uiIndex]; + return m_SkillIndexDefs[uiIndex].get(); } CSkillDef* CServerConfig::GetSkillDef( SKILL_TYPE index ) @@ -1471,9 +1471,9 @@ CSkillDef* CServerConfig::GetSkillDef( SKILL_TYPE index ) if (index < 0) return nullptr; const size_t uiIndex = (size_t)index; - if (!m_SkillIndexDefs.IsValidIndex(uiIndex) ) + if (!m_SkillIndexDefs.valid_index(uiIndex) ) return nullptr; - return m_SkillIndexDefs[uiIndex]; + return m_SkillIndexDefs[uiIndex].get(); } const CSkillDef* CServerConfig::FindSkillDef( lpctstr ptcKey ) const @@ -1494,7 +1494,7 @@ const CSkillDef * CServerConfig::SkillLookup( lpctstr ptcKey ) const CSkillDef * pDef; for ( size_t i = 0; i < m_SkillIndexDefs.size(); ++i ) { - pDef = static_cast(m_SkillIndexDefs[i]); + pDef = static_cast(m_SkillIndexDefs[i].get()); ASSERT(pDef); if ( !strnicmp(ptcKey, (pDef->m_sName.IsEmpty() ? pDef->GetKey() : pDef->m_sName.GetBuffer()), iLen) ) return pDef; @@ -1673,7 +1673,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * { for (size_t i = 0; i < g_World.m_Multis.size(); ++i) { - pMulti = g_World.m_Multis[i]; + pMulti = g_World.m_Multis[i].get(); if (pMulti == nullptr) continue; @@ -1695,7 +1695,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * for (size_t i = 0; i < g_World.m_Multis.size(); ++i) { - pMulti = g_World.m_Multis[i]; + pMulti = g_World.m_Multis[i].get(); if (pMulti == nullptr) continue; @@ -1770,7 +1770,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * { for ( size_t i = 0; i < g_World.m_Stones.size(); ++i ) { - pStone = g_World.m_Stones[i]; + pStone = g_World.m_Stones[i].get(); if ( pStone == nullptr ) continue; @@ -1790,7 +1790,7 @@ bool CServerConfig::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * for ( size_t i = 0; i < g_World.m_Stones.size(); ++i ) { - pStone = g_World.m_Stones[i]; + pStone = g_World.m_Stones[i].get(); if ( pStone == nullptr ) continue; @@ -2211,7 +2211,7 @@ SKILL_TYPE CServerConfig::FindSkillKey( lpctstr ptcKey ) const if ( IsDigit( ptcKey[0] ) ) { SKILL_TYPE skill = (SKILL_TYPE)(Exp_GetVal(ptcKey)); - if ( ( !CChar::IsSkillBase(skill) || !m_SkillIndexDefs.IsValidIndex(skill) ) && !CChar::IsSkillNPC(skill) ) + if ( ( !CChar::IsSkillBase(skill) || !m_SkillIndexDefs.valid_index(skill) ) && !CChar::IsSkillNPC(skill) ) return SKILL_NONE; return skill; } @@ -2335,7 +2335,7 @@ CWebPageDef * CServerConfig::FindWebPage( lpctstr pszPath ) const if (m_WebPages.empty()) return nullptr; // Take this as the default page. - return static_cast ( m_WebPages[0] ); + return static_cast ( m_WebPages[0].get() ); } lpctstr pszTitle = CSFile::GetFilesTitle(pszPath); @@ -2346,7 +2346,7 @@ CWebPageDef * CServerConfig::FindWebPage( lpctstr pszPath ) const if (m_WebPages.size() <= 0 ) return nullptr; // Take this as the default page. - return static_cast ( m_WebPages[0] ); + return static_cast ( m_WebPages[0].get() ); } for ( size_t i = 0; i < m_WebPages.size(); ++i ) @@ -2354,7 +2354,7 @@ CWebPageDef * CServerConfig::FindWebPage( lpctstr pszPath ) const if ( m_WebPages[i] == nullptr ) // not sure why this would happen continue; - CWebPageDef * pWeb = static_cast (m_WebPages[i] ); + CWebPageDef * pWeb = static_cast (m_WebPages[i].get() ); ASSERT(pWeb); if ( pWeb->IsMatch(pszTitle)) return pWeb; @@ -2694,7 +2694,7 @@ void CServerConfig::LoadSortSpells() for ( size_t i = 1; i < iQtySpells; ++i ) { - if ( !m_SpellDefs.IsValidIndex( i ) ) + if ( !m_SpellDefs.valid_index( i ) ) continue; int iVal = 0; @@ -2706,14 +2706,14 @@ void CServerConfig::LoadSortSpells() while ( k < iQty ) { int iVal2 = 0; - if (m_SpellDefs_Sorted[k]->GetPrimarySkill(nullptr, &iVal2)) + if (m_SpellDefs_Sorted[k].lock()->GetPrimarySkill(nullptr, &iVal2)) { if (iVal2 > iVal) break; } ++k; } - m_SpellDefs_Sorted.insert(k, m_SpellDefs[i]); + m_SpellDefs_Sorted.emplace_index_grow(k, m_SpellDefs[i]); } } @@ -2933,7 +2933,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) CResourceDef * pRes = nullptr; size_t index = m_ResHash.FindKey( rid ); if ( index != SCONT_BADINDEX ) - pRes = dynamic_cast (m_ResHash.GetAt( rid, index ) ); + pRes = dynamic_cast (m_ResHash.GetBarePtrAt( rid, index ) ); if ( pRes == nullptr ) { @@ -2970,7 +2970,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) CResourceLink * pNewLink = nullptr; CResourceDef * pNewDef = nullptr; - CResourceDef * pPrvDef = nullptr; + CResourceDef * pPrvDef; if ( m_ResourceList.ContainsKey( const_cast(pszSection) )) { @@ -2991,7 +2991,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) return true; case RES_SPHERECRYPT: - CCrypto::LoadKeyTable(*pScript); + CCryptoKeysHolder::get()->LoadKeyTable(*pScript); return true; case RES_ACCOUNT: // NOTE: ArgStr is not the DEFNAME @@ -3200,7 +3200,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_SPELL: { CSpellDef * pSpell; - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) pSpell = dynamic_cast(pPrvDef); else @@ -3213,21 +3213,21 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) pScript->SeekContext( LineContext ); if ( !pPrvDef ) - m_SpellDefs.assign_at_grow(rid.GetResIndex(), pSpell); + m_SpellDefs.emplace_index_grow(rid.GetResIndex(), std::shared_ptr(pSpell)); } break; case RES_SKILL: { CSkillDef * pSkill; - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) { pSkill = dynamic_cast (pPrvDef); } else { - if ( rid.GetResIndex() >= (int)(m_iMaxSkill) ) + if ( rid.GetResIndex() >= (uint)(m_iMaxSkill) ) m_iMaxSkill = rid.GetResIndex() + 1; // Just replace any previous CSkillDef @@ -3246,7 +3246,8 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) // build a name sorted list. m_SkillNameDefs.emplace(pSkill); // Hard coded value for skill index. - m_SkillIndexDefs.assign_at_grow(rid.GetResIndex(), pSkill); + uint idx = rid.GetResIndex(); + m_SkillIndexDefs.emplace_index_grow(idx, std::shared_ptr(pSkill)); } } break; @@ -3266,8 +3267,9 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) const size_t iQty = g_World.m_TileTypes.size(); for ( size_t i = 0; i < iQty; ++i ) { - if (g_World.m_TileTypes[i] == pTypeDef ) - g_World.m_TileTypes.assign_at(i, nullptr); + auto pCurTypeDef = static_cast(g_World.m_TileTypes[i].lock().get()); + if (pCurTypeDef == pTypeDef) + g_World.m_TileTypes.emplace_index_grow(i, nullptr); } } @@ -3300,7 +3302,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_SCROLL: case RES_SKILLMENU: // Just index this for access later. - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) { pNewLink = dynamic_cast (pPrvDef); @@ -3318,7 +3320,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) break; case RES_DIALOG: // Just index this for access later. - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) { pNewLink = dynamic_cast (pPrvDef); @@ -3337,7 +3339,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_REGIONRESOURCE: // No need to Link to this really . - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) { pNewLink = dynamic_cast ( pPrvDef ); @@ -3360,7 +3362,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) break; case RES_AREA: - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef && fNewStyleDef ) { CRegionWorld * pRegion = dynamic_cast ( pPrvDef ); @@ -3392,7 +3394,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) } break; case RES_ROOM: - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef && fNewStyleDef ) { CRegion * pRegion = dynamic_cast ( pPrvDef ); @@ -3426,7 +3428,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_REGIONTYPE: case RES_SPAWN: case RES_TEMPLATE: - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef ) { pNewLink = dynamic_cast (pPrvDef); @@ -3450,7 +3452,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_CHAMPION: { - pPrvDef = ResourceGetDef(rid); + pPrvDef = RegisteredResourceGetDef(rid); if (pPrvDef) { pNewLink = dynamic_cast (pPrvDef); @@ -3475,7 +3477,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) break; } case RES_SKILLCLASS: - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef ) { pNewLink = dynamic_cast (pPrvDef); @@ -3501,7 +3503,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) case RES_ITEMDEF: // ??? existing hard pointers to RES_CHARDEF ? // ??? existing hard pointers to RES_ITEMDEF ? - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef( rid ); if ( pPrvDef ) { pNewLink = dynamic_cast(pPrvDef); @@ -3534,7 +3536,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) // ??? existing hard pointers to areas ? case RES_WEBPAGE: // Read a web page entry. - pPrvDef = ResourceGetDef( rid ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef ) { pNewLink = dynamic_cast (pPrvDef); @@ -3629,7 +3631,7 @@ bool CServerConfig::LoadResourceSection( CScript * pScript ) while ( pScript->ReadKeyParse()) { CResourceID ridnew( RES_TYPEDEF, pScript->GetArgVal() ); - pPrvDef = ResourceGetDef( ridnew ); + pPrvDef = RegisteredResourceGetDef(rid); if ( pPrvDef ) { pPrvDef->SetResourceName( pScript->GetKey() ); @@ -3990,7 +3992,7 @@ CResourceID CServerConfig::ResourceGetNewID( RES_TYPE restype, lpctstr pszName, // Warn of duplicates. size_t duplicateIndex = m_ResHash.FindKey( rid ); if ( duplicateIndex != SCONT_BADINDEX ) // i found it. So i have to find something else. - ASSERT(m_ResHash.GetAt(rid, duplicateIndex)); + ASSERT(m_ResHash.GetBarePtrAt(rid, duplicateIndex)); } #endif return rid; @@ -4049,7 +4051,7 @@ CResourceID CServerConfig::ResourceGetNewID( RES_TYPE restype, lpctstr pszName, { DEBUG_ERR(( "WARNING: region redefines DEFNAME='%s' for another region!\n", pszName )); } - else if ( ResourceGetDef(CResourceID(rid.GetResType(), rid.GetResIndex(), wPage)) ) + else if (!RegisteredResourceGetDefRef(CResourceID(rid.GetResType(), rid.GetResIndex(), wPage)).expired() ) { // Books and dialogs have pages; if it's not a book or dialog, the if is 0 == 0, so execute it always @@ -4200,68 +4202,88 @@ CResourceID CServerConfig::ResourceGetNewID( RES_TYPE restype, lpctstr pszName, return rid; } -CResourceDef * CServerConfig::ResourceGetDef( const CResourceID& rid ) const +std::weak_ptr CServerConfig::RegisteredResourceGetDefRefByName(RES_TYPE restype, lpctstr ptcName, word wPage) +{ + ADDTOCALLSTACK("CServerConfig::RegisteredResourceGetDefRefByName"); + return ResourceGetDefRefByName(restype, ptcName, wPage); +} + +std::weak_ptr CServerConfig::RegisteredResourceGetDefRef(const CResourceID& rid) const { - ADDTOCALLSTACK("CServerConfig::ResourceGetDef"); + ADDTOCALLSTACK("CServerConfig::RegisteredResourceGetDefRef"); // Get a CResourceDef from the RESOURCE_ID. // ARGS: // restype = id must be this type. - if ( ! rid.IsValidResource() ) - return nullptr; + if (!rid.IsValidResource()) + return {}; int index = rid.GetResIndex(); - switch ( rid.GetResType() ) + switch (rid.GetResType()) { - case RES_WEBPAGE: - { - size_t i = m_WebPages.find_sorted( rid ); - if ( i == SCONT_BADINDEX ) - return nullptr; - return m_WebPages[i]; - } + case RES_WEBPAGE: + { + const size_t i = m_WebPages.find_sorted(rid); + if (i == SCONT_BADINDEX) + return {}; + return m_WebPages[i]; + } - case RES_SKILL: - if ( ! m_SkillIndexDefs.IsValidIndex(index) ) - return nullptr; - return m_SkillIndexDefs[ index ]; + case RES_SKILL: + if (!m_SkillIndexDefs.valid_index(index)) + return {}; + return m_SkillIndexDefs[index]; - case RES_SPELL: - if ( ! m_SpellDefs.IsValidIndex(index) ) - return nullptr; - return m_SpellDefs[ index ]; + case RES_SPELL: + if (!m_SpellDefs.valid_index(index)) + return {}; + return m_SpellDefs[index]; - case RES_UNKNOWN: // legal to use this as a ref but it is unknown - return nullptr; + case RES_UNKNOWN: // legal to use this as a ref but it is unknown + return {}; - case RES_BOOK: // A book or a page from a book. - case RES_EVENTS: - case RES_DIALOG: // A scriptable gump dialog: text or handler block. - case RES_MENU: - case RES_NAMES: // A block of possible names for a NPC type. (read as needed) - case RES_NEWBIE: // MALE_DEFAULT, FEMALE_DEFAULT, Skill - case RES_REGIONRESOURCE: - case RES_REGIONTYPE: // Triggers etc. that can be assinged to a RES_AREA - case RES_SCROLL: // SCROLL_GUEST=message scroll sent to player at guest login. SCROLL_MOTD: SCROLL_NEWBIE - case RES_SPEECH: - case RES_TIP: // Tips (similar to RES_SCROLL) that can come up at startup. - case RES_TYPEDEF: // Define a trigger block for a RES_WORLDITEM m_type. - case RES_TEMPLATE: - case RES_SKILLMENU: - case RES_ITEMDEF: - case RES_CHARDEF: - case RES_SPAWN: // the char spawn tables - case RES_SKILLCLASS: - case RES_AREA: - case RES_ROOM: - case RES_CHAMPION: - break; + case RES_BOOK: // A book or a page from a book. + case RES_EVENTS: + case RES_DIALOG: // A scriptable gump dialog: text or handler block. + case RES_MENU: + case RES_NAMES: // A block of possible names for a NPC type. (read as needed) + case RES_NEWBIE: // MALE_DEFAULT, FEMALE_DEFAULT, Skill + case RES_REGIONRESOURCE: + case RES_REGIONTYPE: // Triggers etc. that can be assinged to a RES_AREA + case RES_SCROLL: // SCROLL_GUEST=message scroll sent to player at guest login. SCROLL_MOTD: SCROLL_NEWBIE + case RES_SPEECH: + case RES_TIP: // Tips (similar to RES_SCROLL) that can come up at startup. + case RES_TYPEDEF: // Define a trigger block for a RES_WORLDITEM m_type. + case RES_TEMPLATE: + case RES_SKILLMENU: + case RES_ITEMDEF: + case RES_CHARDEF: + case RES_SPAWN: // the char spawn tables + case RES_SKILLCLASS: + case RES_AREA: + case RES_ROOM: + case RES_CHAMPION: + break; - default: - return nullptr; + default: + return {}; } - return CResourceBase::ResourceGetDef( rid ); + return CResourceBase::ResourceGetDefRef(rid); +} + +CResourceDef * CServerConfig::RegisteredResourceGetDef( const CResourceID& rid ) const +{ + ADDTOCALLSTACK("CServerConfig::RegisteredResourceGetDef"); + std::shared_ptr ret = RegisteredResourceGetDefRef(rid).lock(); + return ret ? ret.get() : nullptr; +} + +CResourceDef* CServerConfig::RegisteredResourceGetDefByName(RES_TYPE restype, lpctstr ptcName, word wPage) +{ + ADDTOCALLSTACK("CServerConfig::RegisteredResourceGetDefByName"); + std::shared_ptr ret = RegisteredResourceGetDefRefByName(restype, ptcName, wPage).lock(); + return ret ? ret.get() : nullptr; } //////////////////////////////////////////////////////////////////////////////// @@ -4281,7 +4303,7 @@ void CServerConfig::_OnTick( bool fNow ) EXC_TRY("WebTick"); if ( !m_WebPages[i] ) continue; - CWebPageDef * pWeb = static_cast (m_WebPages[i]); + CWebPageDef * pWeb = static_cast (m_WebPages[i].get()); if ( pWeb ) { pWeb->WebPageUpdate(fNow, nullptr, &g_Serv); @@ -4290,7 +4312,7 @@ void CServerConfig::_OnTick( bool fNow ) EXC_CATCH; EXC_DEBUG_START; - CWebPageDef * pWeb = static_cast (m_WebPages[i]); + CWebPageDef * pWeb = static_cast (m_WebPages[i].get()); g_Log.EventDebug("web '%s' dest '%s' now '%d' index '%" PRIuSIZE_T "'/'%" PRIuSIZE_T "'\n", pWeb ? pWeb->GetName() : "", pWeb ? pWeb->GetDstName() : "", fNow? 1 : 0, i, m_WebPages.size()); @@ -4417,7 +4439,8 @@ bool CServerConfig::LoadCryptIni( void ) m_scpCryptIni.Close(); m_scpCryptIni.CloseForce(); - g_Log.Event( LOGM_INIT, "Loaded %" PRIuSIZE_T " client encryption keys.\n", CCrypto::client_keys.size() ); + g_Log.Event( LOGM_INIT, "Loaded %" PRIuSIZE_T " client encryption keys.\n", + CCryptoKeysHolder::get()->client_keys.size() ); return true; } @@ -4623,7 +4646,7 @@ bool CServerConfig::Load( bool fResync ) g_Serv.SetName(( ! iRet && szName[0] ) ? szName : SPHERE_TITLE ); } - if ( ! ResourceGetDef( CResourceID( RES_SKILLCLASS, 0 ))) + if ( RegisteredResourceGetDefRef( CResourceID( RES_SKILLCLASS, 0 )).expired() ) { // must have at least 1 skill class. CSkillClassDef * pSkillClass = new CSkillClassDef( CResourceID( RES_SKILLCLASS )); diff --git a/src/game/CServerConfig.h b/src/game/CServerConfig.h index 0552ac3dd..ce2f562b8 100644 --- a/src/game/CServerConfig.h +++ b/src/game/CServerConfig.h @@ -7,6 +7,7 @@ #define _INC_CSERVERCONFIG_H #include "../common/sphere_library/CSAssoc.h" +#include "../common/sphere_library/sptr_containers.h" #include "../common/resource/sections/CSkillDef.h" #include "../common/resource/sections/CSpellDef.h" #include "../common/resource/sections/CWebPageDef.h" @@ -587,9 +588,9 @@ extern class CServerConfig : public CResourceBase CMultiDefArray m_MultiDefs; // read from the MUL files. Cached here on demand. CObjNameSortVector m_SkillNameDefs; // const CSkillDef* Name sorted. - CSPtrTypeArray< CSkillDef* > m_SkillIndexDefs; // Defined Skills indexed by number. - CSObjArray< CSpellDef* > m_SpellDefs; // Defined Spells. - CSPtrTypeArray< CSpellDef* > m_SpellDefs_Sorted; // Defined Spells, in skill order. + CSSharedPtrVector m_SkillIndexDefs; // Defined Skills indexed by number. + CSSharedPtrVector m_SpellDefs; // Defined Spells. + CSWeakPtrVector m_SpellDefs_Sorted; // Defined Spells, in skill order. CSStringSortArray m_PrivCommands[PLEVEL_QTY]; // what command are allowed for a priv level? @@ -671,6 +672,21 @@ extern class CServerConfig : public CResourceBase */ void LoadSortSpells(); + + /** + * @brief Get a CResourceDef from the RESOURCE_ID. + * + * @param restype Resource Type. + * + * @param ptcName Resource Name. + * + * @param wPage Resource Page attribute. + * + * @return null if it fails, else a pointer to the CScriptObj. + */ + std::weak_ptr RegisteredResourceGetDefRefByName(RES_TYPE restype, lpctstr pszName, word wPage = 0); + CResourceDef* RegisteredResourceGetDefByName(RES_TYPE restype, lpctstr pszName, word wPage = 0); + /** * @brief Get a CResourceDef from the RESOURCE_ID. * @@ -678,7 +694,9 @@ extern class CServerConfig : public CResourceBase * * @return null if it fails, else a pointer to a CResourceDef. */ - virtual CResourceDef * ResourceGetDef( const CResourceID& rid ) const override; + //CResourceDef * RegisteredResourceGetDefRef( const CResourceID& rid ) const; + std::weak_ptr RegisteredResourceGetDefRef(const CResourceID& rid) const; + CResourceDef* RegisteredResourceGetDef(const CResourceID& rid) const; // Print EF/OF Flags void PrintEFOFFlags( bool bEF = true, bool bOF = true, CTextConsole *pSrc = nullptr ); diff --git a/src/game/CWorld.cpp b/src/game/CWorld.cpp index 397627f11..0d02c7e61 100644 --- a/src/game/CWorld.cpp +++ b/src/game/CWorld.cpp @@ -8,6 +8,7 @@ #include "chars/CChar.h" #include "clients/CClient.h" #include "clients/CGMPage.h" +#include "items/CItemMulti.h" #include "CServer.h" #include "CScriptProfiler.h" #include "CSector.h" @@ -1618,7 +1619,7 @@ void CWorld::Restock() { for ( size_t j = 0; j < g_Cfg.m_ResHash.m_Array[i].size(); ++j ) { - CResourceDef * pResDef = g_Cfg.m_ResHash.m_Array[i][j]; + CResourceDef * pResDef = g_Cfg.m_ResHash.m_Array[i][j].get(); if ( pResDef == nullptr || ( pResDef->GetResType() != RES_ITEMDEF )) continue; diff --git a/src/game/CWorld.h b/src/game/CWorld.h index ff11a88c5..19122ac9b 100644 --- a/src/game/CWorld.h +++ b/src/game/CWorld.h @@ -8,6 +8,7 @@ #include "../common/sphere_library/CSObjCont.h" #include "../common/sphere_library/CSObjList.h" +#include "../common/sphere_library/sptr_containers.h" #include "../common/CScript.h" #include "../common/CUID.h" #include "CSectorList.h" @@ -15,7 +16,7 @@ #include "CWorldClock.h" #include "CWorldTicker.h" -class CItemTypeDef; +class CResourceDef; class CSector; class CObjBaseTemplate; class CObjBase; @@ -160,13 +161,13 @@ extern class CWorld : public CScriptObj, public CWorldThread CSObjList m_GMPages; // Current outstanding GM pages. (CGMPage) - CSPtrTypeArray m_Stones; // links to leige/town stones. (not saved array) + CSUniquePtrVector m_Stones; // links to leige/town stones. (not saved array) CSObjList m_Parties; // links to all active parties. CPartyDef static lpctstr const sm_szLoadKeys[]; - CSPtrTypeArray m_TileTypes; + CSWeakPtrVector m_TileTypes; // CItemTypeDef - CSPtrTypeArray m_Multis; // + CSUniquePtrVector m_Multis; // private: bool LoadFile( lpctstr pszName, bool fError = true ); diff --git a/src/game/CWorldImport.cpp b/src/game/CWorldImport.cpp index 828f64bbe..557b53e81 100644 --- a/src/game/CWorldImport.cpp +++ b/src/game/CWorldImport.cpp @@ -614,7 +614,7 @@ bool CImportFile::ImportWSC( CScript & s, word wModeFlags ) else if ( s.IsKeyHead( "SKILL", 5 )) { SKILL_TYPE skill = (SKILL_TYPE)(atoi( &(s.GetKey()[5]) )); - if ( pChar->IsSkillBase(skill) && g_Cfg.m_SkillIndexDefs.IsValidIndex(skill) ) + if ( pChar->IsSkillBase(skill) && g_Cfg.m_SkillIndexDefs.valid_index(skill) ) pChar->Skill_SetBase( skill, (ushort)atoi(pArg)); } else if ( s.IsKey("ACCOUNT" )) diff --git a/src/game/CWorldMap.cpp b/src/game/CWorldMap.cpp index 871ac0350..2398601f6 100644 --- a/src/game/CWorldMap.cpp +++ b/src/game/CWorldMap.cpp @@ -179,9 +179,9 @@ CItemTypeDef* CWorldMap::GetTerrainItemTypeDef(dword dwTerrainIndex) // static ADDTOCALLSTACK("CWorldMap::GetTerrainItemTypeDef"); CResourceDef* pRes = nullptr; - if (g_World.m_TileTypes.IsValidIndex(dwTerrainIndex)) + if (g_World.m_TileTypes.valid_index(dwTerrainIndex)) { - pRes = g_World.m_TileTypes[dwTerrainIndex]; + pRes = static_cast(g_World.m_TileTypes[dwTerrainIndex].lock().get()); } if (!pRes) @@ -202,9 +202,9 @@ IT_TYPE CWorldMap::GetTerrainItemType(dword dwTerrainIndex) // static ADDTOCALLSTACK("CWorldMap::GetTerrainItemType"); CResourceDef* pRes = nullptr; - if (g_World.m_TileTypes.IsValidIndex(dwTerrainIndex)) + if (g_World.m_TileTypes.valid_index(dwTerrainIndex)) { - pRes = g_World.m_TileTypes[dwTerrainIndex]; + pRes = static_cast(g_World.m_TileTypes[dwTerrainIndex].lock().get()); } if (!pRes) diff --git a/src/game/chars/CChar.cpp b/src/game/chars/CChar.cpp index e770944f1..f41475ba3 100644 --- a/src/game/chars/CChar.cpp +++ b/src/game/chars/CChar.cpp @@ -1686,7 +1686,7 @@ void CChar::InitPlayer( CClient *pClient, const char *pszCharname, bool fFemale, // randomize the skills first. for ( uint i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( g_Cfg.m_SkillIndexDefs.IsValidIndex(i) ) + if ( g_Cfg.m_SkillIndexDefs.valid_index(i) ) Skill_SetBase((SKILL_TYPE)i, (ushort)Calc_GetRandVal(g_Cfg.m_iMaxBaseSkill)); } @@ -1719,15 +1719,15 @@ void CChar::InitPlayer( CClient *pClient, const char *pszCharname, bool fFemale, Stat_SetBase(STAT_DEX, wDex); Stat_SetBase(STAT_INT, wInt); - if ( IsSkillBase(skSkill1) && g_Cfg.m_SkillIndexDefs.IsValidIndex(skSkill1) ) + if ( IsSkillBase(skSkill1) && g_Cfg.m_SkillIndexDefs.valid_index(skSkill1) ) Skill_SetBase(skSkill1, uiSkillVal1 * 10); - if ( IsSkillBase(skSkill2) && g_Cfg.m_SkillIndexDefs.IsValidIndex(skSkill2) ) + if ( IsSkillBase(skSkill2) && g_Cfg.m_SkillIndexDefs.valid_index(skSkill2) ) Skill_SetBase(skSkill2, uiSkillVal2 * 10); - if ( IsSkillBase(skSkill3) && g_Cfg.m_SkillIndexDefs.IsValidIndex(skSkill3) ) + if ( IsSkillBase(skSkill3) && g_Cfg.m_SkillIndexDefs.valid_index(skSkill3) ) Skill_SetBase(skSkill3, uiSkillVal3 * 10); if ( skSkill4 != SKILL_NONE ) { - if ( IsSkillBase(skSkill4) && g_Cfg.m_SkillIndexDefs.IsValidIndex(skSkill4) ) + if ( IsSkillBase(skSkill4) && g_Cfg.m_SkillIndexDefs.valid_index(skSkill4) ) Skill_SetBase(skSkill4, uiSkillVal4 * 10); } @@ -3965,7 +3965,7 @@ void CChar::r_Write( CScript & s ) for ( uint j = 0; j < g_Cfg.m_iMaxSkill; ++j ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)j) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)j) ) continue; const ushort uiSkillVal = Skill_GetBase((SKILL_TYPE)j); if (uiSkillVal == 0) @@ -4100,7 +4100,7 @@ bool CChar::r_Verb( CScript &s, CTextConsole * pSrc ) // Execute command from sc ushort uiVal = s.GetArgUSVal(); for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i) ) continue; Skill_SetBase((SKILL_TYPE)i, uiVal ); @@ -4647,7 +4647,7 @@ bool CChar::OnTriggerSpeech( bool bIsPet, lpctstr pszText, CChar * pSrc, TALKMOD goto lbl_cchar_ontriggerspeech; { - CScriptObj * pDef = g_Cfg.ResourceGetDefByName( RES_SPEECH, pszName ); + CScriptObj * pDef = g_Cfg.RegisteredResourceGetDefByName( RES_SPEECH, pszName ); if ( pDef ) { CResourceLink * pLink = dynamic_cast ( pDef ); diff --git a/src/game/chars/CCharBase.cpp b/src/game/chars/CCharBase.cpp index df7c83839..1ebe6aaa1 100644 --- a/src/game/chars/CCharBase.cpp +++ b/src/game/chars/CCharBase.cpp @@ -501,7 +501,7 @@ CCharBase * CCharBase::FindCharBase( CREID_TYPE baseID ) // static if ( index == SCONT_BADINDEX ) return nullptr; - CResourceLink * pBaseLink = static_cast ( g_Cfg.m_ResHash.GetAt(rid,index)); + CResourceLink * pBaseLink = static_cast (g_Cfg.m_ResHash.GetBarePtrAt(rid,index)); ASSERT(pBaseLink); CCharBase * pBase = dynamic_cast (pBaseLink); if ( pBase ) diff --git a/src/game/chars/CCharNPCAct_Vendor.cpp b/src/game/chars/CCharNPCAct_Vendor.cpp index 37f70b30f..a0f8b9279 100644 --- a/src/game/chars/CCharNPCAct_Vendor.cpp +++ b/src/game/chars/CCharNPCAct_Vendor.cpp @@ -243,7 +243,7 @@ ushort CChar::NPC_OnTrainCheck( CChar * pCharSrc, SKILL_TYPE Skill ) { for (uint i = 0; i < g_Cfg.m_iMaxSkill; ++i) { - if (!g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i)) + if (!g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i)) continue; if (pCharSrc->Skill_GetLock((SKILL_TYPE)i) == SKILLLOCK_DOWN) @@ -280,7 +280,7 @@ bool CChar::NPC_OnTrainPay(CChar *pCharSrc, CItemMemory *pMemory, CItem * pGold) ASSERT(m_pNPC); SKILL_TYPE skill = (SKILL_TYPE)(pMemory->m_itEqMemory.m_Skill); - if ( !IsSkillBase(skill) || !g_Cfg.m_SkillIndexDefs.IsValidIndex(skill) ) + if ( !IsSkillBase(skill) || !g_Cfg.m_SkillIndexDefs.valid_index(skill) ) { Speak(g_Cfg.GetDefaultMsg(DEFMSG_NPC_TRAINER_FORGOT)); return false; @@ -340,7 +340,7 @@ bool CChar::NPC_TrainSkill( CChar * pCharSrc, SKILL_TYPE skill, ushort uiAmountT { for ( uint i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i) ) continue; if ( uiAmountToTrain < 1 ) @@ -393,7 +393,7 @@ bool CChar::NPC_OnTrainHear( CChar * pCharSrc, lpctstr pszCmd ) TemporaryString tsMsg; for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i) ) continue; lpctstr pSkillKey = g_Cfg.GetSkillKey((SKILL_TYPE)i); @@ -424,7 +424,7 @@ bool CChar::NPC_OnTrainHear( CChar * pCharSrc, lpctstr pszCmd ) uint iCount = 0; for ( uint i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i) ) continue; const int iDiff = NPC_GetTrainMax(pCharSrc, (SKILL_TYPE)i) - pCharSrc->Skill_GetBase((SKILL_TYPE)i); diff --git a/src/game/chars/CCharPlayer.cpp b/src/game/chars/CCharPlayer.cpp index 2bd978268..532638b82 100644 --- a/src/game/chars/CCharPlayer.cpp +++ b/src/game/chars/CCharPlayer.cpp @@ -70,7 +70,7 @@ CMultiStorage* CCharPlayer::GetMultiStorage() bool CCharPlayer::SetSkillClass( CChar * pChar, CResourceID rid ) { ADDTOCALLSTACK("CCharPlayer::SetSkillClass"); - CResourceDef * pDef = g_Cfg.ResourceGetDef(rid); + CResourceDef * pDef = g_Cfg.RegisteredResourceGetDef(rid); if ( !pDef ) return false; diff --git a/src/game/chars/CCharSkill.cpp b/src/game/chars/CCharSkill.cpp index 4fce933bb..86a9a8157 100644 --- a/src/game/chars/CCharSkill.cpp +++ b/src/game/chars/CCharSkill.cpp @@ -31,7 +31,7 @@ SKILL_TYPE CChar::Skill_GetBest( uint iRank ) const dword dwSkillTmp; for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex(i) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index(i) ) continue; dwSkillTmp = MAKEDWORD(i, Skill_GetBase((SKILL_TYPE)i)); @@ -320,7 +320,7 @@ void CChar::Skill_Decay() // Look for a skill to deduct from for ( size_t i = 0; i < g_Cfg.m_iMaxSkill; ++i ) { - if ( g_Cfg.m_SkillIndexDefs.IsValidIndex(i) == false ) + if ( g_Cfg.m_SkillIndexDefs.valid_index(i) == false ) continue; // Check that the skill is set to decrease and that it is not already at 0 @@ -363,7 +363,7 @@ void CChar::Skill_Experience( SKILL_TYPE skill, int iDifficulty ) // ARGS: // difficulty = skill target from 0-100 - if ( !IsSkillBase(skill) || !g_Cfg.m_SkillIndexDefs.IsValidIndex(skill) ) + if ( !IsSkillBase(skill) || !g_Cfg.m_SkillIndexDefs.valid_index(skill) ) return; if ( m_pArea && m_pArea->IsFlag( REGION_FLAG_SAFE )) // skills don't advance in safe areas. return; @@ -4299,7 +4299,7 @@ bool CChar::Skill_Start( SKILL_TYPE skill, int iDifficultyIncrease ) pArgs.m_iN2 = iWaitTime; // Execute the @START trigger and pass various craft parameters there - CResourceID pResBase(RES_ITEMDEF, fCraftSkill ? m_atCreate.m_iItemID : 0, 0); + CResourceID pResBase(RES_ITEMDEF, (fCraftSkill ? m_atCreate.m_iItemID : ITEMID_NOTHING), 0); if ( fCraftSkill ) { diff --git a/src/game/chars/CCharSpell.cpp b/src/game/chars/CCharSpell.cpp index 1695997c4..3f2da7557 100644 --- a/src/game/chars/CCharSpell.cpp +++ b/src/game/chars/CCharSpell.cpp @@ -2433,7 +2433,7 @@ bool CChar::Spell_CanCast( SPELL_TYPE &spellRef, bool fTest, CObjBase * pSrc, bo { if ( fFailMsg ) { - const CResourceDef * pReagDef = g_Cfg.ResourceGetDef((pSpellDef->m_Reags)[iMissingReagents].GetResourceID() ); + const CResourceDef * pReagDef = g_Cfg.RegisteredResourceGetDef((pSpellDef->m_Reags)[iMissingReagents].GetResourceID() ); SysMessagef( g_Cfg.GetDefaultMsg( DEFMSG_SPELL_TRY_NOREGS ), pReagDef ? pReagDef->GetName() : g_Cfg.GetDefaultMsg( DEFMSG_SPELL_TRY_THEREG ) ); } return false; diff --git a/src/game/chars/CCharUse.cpp b/src/game/chars/CCharUse.cpp index 481479737..1a75cf365 100644 --- a/src/game/chars/CCharUse.cpp +++ b/src/game/chars/CCharUse.cpp @@ -790,7 +790,7 @@ bool CChar::Use_Repair( CItem * pItemArmor ) if ( iMissing != SCONT_BADINDEX ) { // Need this to repair. - const CResourceDef *pCompDef = g_Cfg.ResourceGetDef(pItemDef->m_BaseResources.at(iMissing).GetResourceID()); + const CResourceDef *pCompDef = g_Cfg.RegisteredResourceGetDef(pItemDef->m_BaseResources.at(iMissing).GetResourceID()); SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_LACK_1), pCompDef ? pCompDef->GetName() : g_Cfg.GetDefaultMsg(DEFMSG_REPAIR_LACK_2)); return false; } diff --git a/src/game/clients/CChatChannel.cpp b/src/game/clients/CChatChannel.cpp index 06bf672e3..cb8bbf24b 100644 --- a/src/game/clients/CChatChannel.cpp +++ b/src/game/clients/CChatChannel.cpp @@ -170,11 +170,11 @@ void CChatChannel::RenameChannel(CChatChanMember * pBy, lpctstr pszName) void CChatChannel::KickAll(CChatChanMember * pMemberException) { ADDTOCALLSTACK("CChatChannel::KickAll"); - for (size_t i = 0; i < m_Members.size(); i++) + for (size_t i = 0; i < m_Members.size(); ++i) { - if ( m_Members[i] == pMemberException) // If it's not me, then kick them + if ( m_Members[i].get() == pMemberException) // If it's not me, then kick them continue; - KickMember( pMemberException, m_Members[i] ); + KickMember( pMemberException, m_Members[i].get() ); } } @@ -189,18 +189,18 @@ void CChatChannel::RemoveMember(CChatChanMember * pMember) if ( pClient == nullptr ) // auto-remove offline clients { m_Members[i]->SetChannel(nullptr); - m_Members.erase_at(i); + m_Members.remove(i); continue; } pClient->addChatSystemMessage(CHATMSG_RemoveMember, pMember->GetChatName()); - if (m_Members[i] == pMember) // disjoin + if (m_Members[i].get() == pMember) // disjoin { - m_Members.erase_at(i); + m_Members.remove(i); break; } - i++; + ++i; } // Update our persona @@ -212,7 +212,7 @@ CChatChanMember * CChatChannel::FindMember(lpctstr pszName) const size_t i = FindMemberIndex( pszName ); if ( i == SCONT_BADINDEX ) return nullptr; - return m_Members[i]; + return m_Members[i].get(); } bool CChatChannel::RemoveMember(lpctstr pszName) @@ -261,13 +261,13 @@ void CChatChannel::SetModerator(lpctstr pszMember, bool fFlag) if (m_Moderators[i]->Compare(pszMember) == 0) { if (fFlag == false) - m_Moderators.erase_at(i); + m_Moderators.remove(i); return; } } if (fFlag) { - m_Moderators.push_back(new CSString(pszMember)); + m_Moderators.emplace_back(std::make_unique(pszMember)); } } @@ -319,7 +319,7 @@ bool CChatChannel::AddMember(CChatChanMember * pMember) { ADDTOCALLSTACK("CChatChannel::AddMember"); pMember->SetChannel(this); - m_Members.push_back(pMember); + m_Members.emplace_back(pMember); // See if only moderators have a voice by default lpctstr pszName = pMember->GetChatName(); if (!GetVoiceDefault() && !IsModerator(pszName)) @@ -332,10 +332,10 @@ bool CChatChannel::AddMember(CChatChanMember * pMember) void CChatChannel::SendMembers(CChatChanMember * pMember) { ADDTOCALLSTACK("CChatChannel::SendMembers"); - for (size_t i = 0; i < m_Members.size(); i++) + for (size_t i = 0; i < m_Members.size(); ++i) { CSString sName; - g_Serv.m_Chats.DecorateName(sName, m_Members[i]); + g_Serv.m_Chats.DecorateName(sName, m_Members[i].get()); pMember->SendChatMsg(CHATMSG_SendPlayerName, sName); } } @@ -374,13 +374,13 @@ void CChatChannel::SetVoice(lpctstr pszName, bool fFlag) if (m_NoVoices[i]->Compare(pszName) == 0) { if (fFlag == true) - m_NoVoices.erase_at(i); + m_NoVoices.remove(i); return; } } if (fFlag == false) { - m_NoVoices.push_back(new CSString(pszName)); + m_NoVoices.emplace_back(std::make_unique(pszName)); return; } } diff --git a/src/game/clients/CChatChannel.h b/src/game/clients/CChatChannel.h index 2fd00af9f..028b04ec6 100644 --- a/src/game/clients/CChatChannel.h +++ b/src/game/clients/CChatChannel.h @@ -7,8 +7,8 @@ #define _INC_CCHATCHANNEL_H #include "../../common/sphere_library/CSObjListRec.h" -#include "../../common/sphere_library/CSObjArray.h" #include "../../common/sphere_library/CSString.h" +#include "../../common/sphere_library/sptr_containers.h" #include "../../common/sphereproto.h" @@ -25,9 +25,9 @@ class CChatChannel : public CSObjListRec bool m_fVoiceDefault; // give others voice by default. public: static const char *m_sClassName; - CSObjArray< CSString * > m_NoVoices;// Current list of channel members with no voice - CSObjArray< CSString * > m_Moderators;// Current list of channel's moderators (may or may not be currently in the channel) - CSPtrTypeArray< CChatChanMember* > m_Members; // Current list of members in this channel + CSUniquePtrVector m_NoVoices;// Current list of channel members with no voice + CSUniquePtrVector m_Moderators;// Current list of channel's moderators (may or may not be currently in the channel) + CSUniquePtrVector m_Members; // Current list of members in this channel private: void SetModerator(lpctstr pszName, bool fFlag = true); void SetVoice(lpctstr pszName, bool fFlag = true); diff --git a/src/game/clients/CClientDialog.cpp b/src/game/clients/CClientDialog.cpp index 00bb2ea64..16f62f5a8 100644 --- a/src/game/clients/CClientDialog.cpp +++ b/src/game/clients/CClientDialog.cpp @@ -16,7 +16,7 @@ bool CClient::Dialog_Setup( CLIMODE_TYPE mode, const CResourceID& rid, int iPage if ( pObj == nullptr ) return false; - CResourceDef * pRes = g_Cfg.ResourceGetDef( rid ); + CResourceDef * pRes = g_Cfg.RegisteredResourceGetDef( rid ); CDialogDef * pDlg = dynamic_cast (pRes); if ( !pRes || !pDlg ) { diff --git a/src/game/clients/CClientEvent.cpp b/src/game/clients/CClientEvent.cpp index 562298585..f7c89e136 100644 --- a/src/game/clients/CClientEvent.cpp +++ b/src/game/clients/CClientEvent.cpp @@ -615,7 +615,7 @@ void CClient::Event_Skill_Use( SKILL_TYPE skill ) // Skill is clicked on the ski if ( m_pChar == nullptr ) return; - if ( !g_Cfg.m_SkillIndexDefs.IsValidIndex(skill) ) + if ( !g_Cfg.m_SkillIndexDefs.valid_index(skill) ) { SysMessage( "There is no such skill. Please tell support you saw this message."); return; @@ -2616,7 +2616,7 @@ void CClient::Event_AOSPopupMenuRequest( dword uid ) //construct packet after a for (unsigned int i = 0; i < g_Cfg.m_iMaxSkill; ++i) { - if (!g_Cfg.m_SkillIndexDefs.IsValidIndex(i)) + if (!g_Cfg.m_SkillIndexDefs.valid_index(i)) continue; if (i == SKILL_SPELLWEAVING) continue; diff --git a/src/game/clients/CClientMsg.cpp b/src/game/clients/CClientMsg.cpp index f9bf07068..84f87a7f3 100644 --- a/src/game/clients/CClientMsg.cpp +++ b/src/game/clients/CClientMsg.cpp @@ -1247,7 +1247,7 @@ void CClient::addItemName( CItem * pItem ) case IT_ROCK: case IT_WATER: { - CResourceDef *pResDef = g_Cfg.ResourceGetDef(pItem->m_itResource.m_ridRes); + CResourceDef *pResDef = g_Cfg.RegisteredResourceGetDef(pItem->m_itResource.m_ridRes); if ( pResDef ) len += snprintf(szName + len, sizeof(szName) - len, " (%s)", pResDef->GetName()); } @@ -1866,7 +1866,7 @@ void CClient::addSkillWindow(SKILL_TYPE skill, bool fFromInfo) const // Opens th pChar = m_pChar; bool fAllSkills = (skill >= (SKILL_TYPE)(g_Cfg.m_iMaxSkill)); - if (fAllSkills == false && g_Cfg.m_SkillIndexDefs.IsValidIndex(skill) == false) + if (fAllSkills == false && g_Cfg.m_SkillIndexDefs.valid_index(skill) == false) return; if ( IsTrigUsed(TRIGGER_USERSKILLS) ) diff --git a/src/game/clients/CClientMsg_AOSTooltip.cpp b/src/game/clients/CClientMsg_AOSTooltip.cpp index e264256d9..5ccd6a585 100644 --- a/src/game/clients/CClientMsg_AOSTooltip.cpp +++ b/src/game/clients/CClientMsg_AOSTooltip.cpp @@ -637,7 +637,7 @@ void CClient::AOSTooltip_addDefaultItemData(CItem * pItem) CCSpawn* pSpawn = static_cast(pItem->GetComponent(COMP_SPAWN)); if (!pSpawn) break; - CResourceDef * pSpawnCharDef = g_Cfg.ResourceGetDef(pSpawn->GetSpawnID()); + CResourceDef * pSpawnCharDef = g_Cfg.RegisteredResourceGetDef(pSpawn->GetSpawnID()); lpctstr pszName = nullptr; if (pSpawnCharDef) { @@ -669,7 +669,7 @@ void CClient::AOSTooltip_addDefaultItemData(CItem * pItem) CCSpawn* pSpawn = static_cast(pItem->GetComponent(COMP_SPAWN)); if (!pSpawn) break; - CResourceDef * pSpawnItemDef = g_Cfg.ResourceGetDef(pSpawn->GetSpawnID()); + CResourceDef * pSpawnItemDef = g_Cfg.RegisteredResourceGetDef(pSpawn->GetSpawnID()); PUSH_BACK_TOOLTIP(pItem, t = new CClientTooltip(1060658)); // ~1_val~: ~2_val~ t->FormatArgs("Item\t%u %s", pSpawn->GetPile(), pSpawnItemDef ? pSpawnItemDef->GetName() : "none"); diff --git a/src/game/clients/CClientUse.cpp b/src/game/clients/CClientUse.cpp index 600f071eb..3bf016858 100644 --- a/src/game/clients/CClientUse.cpp +++ b/src/game/clients/CClientUse.cpp @@ -732,7 +732,8 @@ bool CClient::Cmd_Skill_Menu( const CResourceID& rid, int iSelect ) } if ( g_Cfg.m_iDebugFlags & DEBUGF_SCRIPTS ) - g_Log.EventDebug("[DEBUG_SCRIPTS] Too many empty skill menus to continue seeking through menu '%s'\n", g_Cfg.ResourceGetDef(rid)->GetResourceName()); + g_Log.EventDebug("[DEBUG_SCRIPTS] Too many empty skill menus to continue seeking through menu '%s'\n", + g_Cfg.RegisteredResourceGetDef(rid)->GetResourceName()); } ASSERT(iShowCount < (int)ARRAY_COUNT(item)); @@ -921,8 +922,10 @@ int CClient::Cmd_Skill_Menu_Build( const CResourceID& rid, int iSelect, CMenuIte if ( sm_iReentrant > 1024 ) { if ( g_Cfg.m_iDebugFlags & DEBUGF_SCRIPTS ) - g_Log.EventDebug("[DEBUG_SCRIPTS] Too many skill menus (circular menus?) to continue searching in menu '%s'\n", g_Cfg.ResourceGetDef(rid)->GetResourceName()); - + { + g_Log.EventDebug("[DEBUG_SCRIPTS] Too many skill menus (circular menus?) to continue searching in menu '%s'\n", + g_Cfg.RegisteredResourceGetDef(rid)->GetResourceName()); + } *fLimitReached = true; } else diff --git a/src/game/clients/CParty.cpp b/src/game/clients/CParty.cpp index 259548964..84a3e1735 100644 --- a/src/game/clients/CParty.cpp +++ b/src/game/clients/CParty.cpp @@ -569,7 +569,7 @@ bool CPartyDef::r_LoadVal( CScript &s ) else { lpctstr ptcArg = s.GetArgStr(); - CResourceLink *m_pTestEvent = dynamic_cast(g_Cfg.ResourceGetDefByName(RES_FUNCTION, ptcArg)); + CResourceLink *m_pTestEvent = dynamic_cast(g_Cfg.RegisteredResourceGetDefByName(RES_FUNCTION, ptcArg)); if ( !m_pTestEvent ) return false; diff --git a/src/game/components/CCChampion.cpp b/src/game/components/CCChampion.cpp index 1515b8298..bc2ff82aa 100644 --- a/src/game/components/CCChampion.cpp +++ b/src/game/components/CCChampion.cpp @@ -87,7 +87,7 @@ void CCChampion::Init() } const int resId = _idSpawn.GetResIndex(); const CResourceIDBase rid(RES_CHAMPION, resId); - CResourceDef* pResDef = g_Cfg.ResourceGetDef(rid); + CResourceDef* pResDef = g_Cfg.RegisteredResourceGetDef(rid); const CCChampionDef* pChampDef = static_cast(pResDef); if (pChampDef == nullptr) { @@ -202,7 +202,7 @@ void CCChampion::SpawnNPC() } else { - CResourceDef* pRes = g_Cfg.ResourceGetDef(_idSpawn); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); if (pChampDef != nullptr) { @@ -237,7 +237,7 @@ void CCChampion::SpawnNPC() return; } rid = CResourceIDBase(RES_CHARDEF, pNpc); - CResourceDef* pDef = g_Cfg.ResourceGetDef(rid); + CResourceDef* pDef = g_Cfg.RegisteredResourceGetDef(rid); if (!pDef) { return; @@ -745,7 +745,7 @@ lpctstr const CCChampion::sm_szVerbKeys[ICHMPV_QTY + 1] = void CCChampion::r_Write(CScript & s) { ADDTOCALLSTACK("CCChampion::r_Write"); - CResourceDef* pRes = g_Cfg.ResourceGetDef(_idSpawn); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); if (!pChampDef) { @@ -873,7 +873,7 @@ bool CCChampion::r_WriteVal(lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc } else // If it doesnt have, then try to retrieve the group from [CHAMPION ] { - CResourceDef* pRes = g_Cfg.ResourceGetDef(_idSpawn); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); if (pChampDef != nullptr) { @@ -1179,7 +1179,7 @@ TRIGRET_TYPE CCChampion::OnTrigger(ITRIG_TYPE trig, CTextConsole* pSrc, CScriptT { lpctstr pszTrigName = CItem::sm_szTrigName[trig]; - CResourceDef* pRes = g_Cfg.ResourceGetDef(_idSpawn); + CResourceDef* pRes = g_Cfg.RegisteredResourceGetDef(_idSpawn); CCChampionDef* pChampDef = static_cast(pRes); CResourceLink* pResourceLink = static_cast (pChampDef); ASSERT(pResourceLink); diff --git a/src/game/components/CCFaction.cpp b/src/game/components/CCFaction.cpp index 324d04875..8a5cae485 100644 --- a/src/game/components/CCFaction.cpp +++ b/src/game/components/CCFaction.cpp @@ -7,9 +7,9 @@ #include "../items/CItem.h" -CFactionDef::CFactionDef() +CFactionDef::CFactionDef() : + _iFaction(FACTION_NONE) { - _iFaction = FACTION_NONE; } NPC_FACTION CFactionDef::GetFactionID() const @@ -168,7 +168,6 @@ lpctstr const CCFaction::sm_szLoadKeys[CHF_QTY + 1] = CCFaction::CCFaction() : CFactionDef(), CComponent(COMP_FACTION) { //ADDTOCALLSTACK_INTENSIVE("CCFaction::CCFaction(FACTION_TYPE)"); - _iFaction = FACTION_NONE; } CCFaction::CCFaction(CCFaction *copy) : CFactionDef(), CComponent(COMP_FACTION) diff --git a/src/game/components/CCSpawn.cpp b/src/game/components/CCSpawn.cpp index 89addc103..2728b4064 100644 --- a/src/game/components/CCSpawn.cpp +++ b/src/game/components/CCSpawn.cpp @@ -138,7 +138,7 @@ const CResourceDef* CCSpawn::_FixDef() const CResourceDef* pResDef; if (resType != RES_UNKNOWN) { - pResDef = g_Cfg.ResourceGetDef(_idSpawn); + pResDef = g_Cfg.RegisteredResourceGetDef(_idSpawn); if (pResDef) return pResDef; // valid spawn } @@ -169,7 +169,7 @@ const CResourceDef* CCSpawn::_FixDef() { // try a spawn group. const CResourceIDBase rid(RES_SPAWN, iIndex); - pResDef = g_Cfg.ResourceGetDef(rid); + pResDef = g_Cfg.RegisteredResourceGetDef(rid); if (pResDef) { g_Log.EventDebug("CCSpawn::FixDef fixed on spawner with UID=0%x a SPAWN type resource from Resource ID 0%" PRIx32 " to 0%" PRIx32 ".\n", uiItemUID, _idSpawn.GetPrivateUID(), rid.GetPrivateUID()); @@ -215,7 +215,7 @@ const CResourceDef* CCSpawn::_FixDef() { // try a template. const CResourceIDBase rid(RES_TEMPLATE, iIndex); - pResDef = g_Cfg.ResourceGetDef(rid); + pResDef = g_Cfg.RegisteredResourceGetDef(rid); if (pResDef) { g_Log.EventDebug("CCSpawn::FixDef fixed on spawner with UID=0%x a TEMPLATE type resource from Resource ID 0%" PRIx32 " to 0%" PRIx32 ".\n", uiItemUID, _idSpawn.GetPrivateUID(), rid.GetPrivateUID()); @@ -262,7 +262,7 @@ uint CCSpawn::WriteName(tchar *ptcOut) const { ADDTOCALLSTACK("CCSpawn::GetName"); lpctstr ptcName = nullptr; - const CResourceDef *pDef = g_Cfg.ResourceGetDef(_idSpawn); + const CResourceDef *pDef = g_Cfg.RegisteredResourceGetDef(_idSpawn); if (pDef != nullptr) ptcName = pDef->GetName(); if (pDef == nullptr || ptcName == nullptr || ptcName[0] == '\0') @@ -938,7 +938,7 @@ bool CCSpawn::r_LoadVal(CScript & s) { // it should be a spawn group. CResourceIDBase ridTemp(RES_SPAWN, iRidIndex); - CResourceDef *pDef = g_Cfg.ResourceGetDef(ridTemp); + CResourceDef *pDef = g_Cfg.RegisteredResourceGetDef(ridTemp); if (pDef) { _idSpawn = ridTemp; @@ -969,7 +969,7 @@ bool CCSpawn::r_LoadVal(CScript & s) { // try a template CResourceIDBase ridTemp(RES_TEMPLATE, iRidIndex); - CResourceDef *pDef = g_Cfg.ResourceGetDef(ridTemp); + CResourceDef *pDef = g_Cfg.RegisteredResourceGetDef(ridTemp); if (pDef) { _idSpawn = ridTemp; diff --git a/src/game/items/CItem.cpp b/src/game/items/CItem.cpp index 32100e392..a67d5c185 100644 --- a/src/game/items/CItem.cpp +++ b/src/game/items/CItem.cpp @@ -3684,7 +3684,7 @@ TRIGRET_TYPE CItem::OnTrigger( lpctstr pszTrigName, CTextConsole * pSrc, CScript EXC_SET_BLOCK("typedef"); { // It has an assigned trigger type. - CResourceLink * pResourceLink = dynamic_cast ( g_Cfg.ResourceGetDef( CResourceID( RES_TYPEDEF, GetType() ))); + CResourceLink * pResourceLink = dynamic_cast ( g_Cfg.RegisteredResourceGetDef( CResourceID( RES_TYPEDEF, GetType() ))); if ( pResourceLink == nullptr ) { const CChar* pChar = pSrc->GetChar(); diff --git a/src/game/items/CItemBase.cpp b/src/game/items/CItemBase.cpp index 17e5ce2cf..0e61349ce 100644 --- a/src/game/items/CItemBase.cpp +++ b/src/game/items/CItemBase.cpp @@ -799,7 +799,7 @@ height_t CItemBase::GetItemHeight( ITEMID_TYPE id, dword *pdwBlockFlags ) // sta size_t index = g_Cfg.m_ResHash.FindKey(rid); if ( index != SCONT_BADINDEX ) // already loaded ? { - CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetAt( rid, index ); + CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetBarePtrAt( rid, index ); ASSERT(pBaseStub); CItemBase * pBase = dynamic_cast (pBaseStub); if ( pBase ) @@ -1352,7 +1352,7 @@ bool CItemBase::r_WriteVal( lpctstr ptcKey, CSString & sVal, CTextConsole * pSrc // sVal.FormatVal( m_type ); { CResourceID rid( RES_TYPEDEF, m_type ); - CResourceDef *pRes = g_Cfg.ResourceGetDef( rid ); + CResourceDef *pRes = g_Cfg.RegisteredResourceGetDef( rid ); if ( !pRes ) sVal.FormatVal( m_type ); else @@ -1814,7 +1814,6 @@ CItemBase * CItemBase::MakeDupeReplacement( CItemBase * pBase, ITEMID_TYPE idmas pBaseDupe->SetHeight( Height ); } ReplaceItemBase( pBase, pBaseDupe ); - delete pBase; // replaced the old base, delete the old one since it's not used anymore return pBaseNew; } @@ -2223,7 +2222,7 @@ CItemBase * CItemBase::FindItemBase( ITEMID_TYPE id ) // static if ( index == SCONT_BADINDEX ) return nullptr; - CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetAt( rid, index ); + CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetBarePtrAt( rid, index ); ASSERT(pBaseStub); CItemBase * pBase = dynamic_cast (pBaseStub); @@ -2318,7 +2317,7 @@ CItemBaseDupe * CItemBaseDupe::GetDupeRef( ITEMID_TYPE id ) // static if ( index == SCONT_BADINDEX ) return nullptr; - CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetAt( rid, index ); + CResourceDef * pBaseStub = g_Cfg.m_ResHash.GetBarePtrAt( rid, index ); CItemBase * pBase = dynamic_cast (pBaseStub); if ( pBase ) diff --git a/src/game/items/CItemMulti.cpp b/src/game/items/CItemMulti.cpp index d7739336a..ccc494386 100644 --- a/src/game/items/CItemMulti.cpp +++ b/src/game/items/CItemMulti.cpp @@ -122,7 +122,7 @@ CItemMulti::~CItemMulti() } MultiUnRealizeRegion(); // unrealize before removed from ground. - g_World.m_Multis.RemovePtr(this); + g_World.m_Multis.remove(this); // Must remove early because virtuals will fail in child destructor. // Attempt to remove all the accessory junk. // NOTE: assume we have already been removed from Top Level diff --git a/src/game/items/CItemStone.cpp b/src/game/items/CItemStone.cpp index 44bdce803..6b0b8939f 100644 --- a/src/game/items/CItemStone.cpp +++ b/src/game/items/CItemStone.cpp @@ -33,7 +33,7 @@ CItemStone::~CItemStone() DeletePrepare(); // Must remove early because virtuals will fail in child destructor. // Remove this stone from the links of guilds in the world - g_World.m_Stones.RemovePtr( this ); + g_World.m_Stones.remove(this); delete _pMultiStorage; // all members are deleted automatically. diff --git a/src/game/spheresvr.cpp b/src/game/spheresvr.cpp index 6c1eae145..fc09574da 100644 --- a/src/game/spheresvr.cpp +++ b/src/game/spheresvr.cpp @@ -32,13 +32,14 @@ // Headers for InitRuntimeStaticMembers #include "clients/CClient.h" - +/* #ifdef _SANITIZERS const char* __asan_default_options() { //return "verbosity=1:malloc_context_size=20"; return "sleep_before_dying=5"; } #endif +*/ // Dynamic allocation of some global stuff std::string g_sServerDescription; diff --git a/src/network/send.cpp b/src/network/send.cpp index a37acdbfa..c0aee2a19 100644 --- a/src/network/send.cpp +++ b/src/network/send.cpp @@ -1113,7 +1113,7 @@ PacketSkills::PacketSkills(const CClient* target, const CChar* character, SKILL_ for (uint i = 0; i < g_Cfg.m_iMaxSkill; ++i) { - if (g_Cfg.m_SkillIndexDefs.IsValidIndex((SKILL_TYPE)i) == false) + if (g_Cfg.m_SkillIndexDefs.valid_index((SKILL_TYPE)i) == false) continue; writeInt16((word)(i + 1)); diff --git a/src/sphere/ProfileTask.cpp b/src/sphere/ProfileTask.cpp index 04fcb54c4..1d232230a 100644 --- a/src/sphere/ProfileTask.cpp +++ b/src/sphere/ProfileTask.cpp @@ -3,7 +3,7 @@ ProfileTask::ProfileTask(PROFILE_TYPE id) : m_context(nullptr), m_previousTask(PROFILE_OVERHEAD) { - m_context = static_cast(ThreadHolder::current()); + m_context = static_cast(ThreadHolder::get()->current()); if (m_context != nullptr) { m_previousTask = m_context->m_profile.GetCurrentTask(); diff --git a/src/sphere/ProfileTask.h b/src/sphere/ProfileTask.h index c38716eff..62805b01f 100644 --- a/src/sphere/ProfileTask.h +++ b/src/sphere/ProfileTask.h @@ -10,7 +10,7 @@ class AbstractSphereThread; -#define CurrentProfileData static_cast(ThreadHolder::current())->m_profile +#define CurrentProfileData static_cast(ThreadHolder::get()->current())->m_profile class ProfileTask diff --git a/src/sphere/ntwindow.cpp b/src/sphere/ntwindow.cpp index 1a0dbf82c..9fa0797f3 100644 --- a/src/sphere/ntwindow.cpp +++ b/src/sphere/ntwindow.cpp @@ -96,10 +96,10 @@ void CNTWindow::CStatusDlg::FillStats() CNTWindow::CListTextConsole capture( m_wndListStats.m_hWnd ); - size_t iThreadCount = ThreadHolder::getActiveThreads(); + size_t iThreadCount = ThreadHolder::get()->getActiveThreads(); for ( size_t iThreads = 0; iThreads < iThreadCount; ++iThreads) { - IThread* thrCurrent = ThreadHolder::getThreadAt(iThreads); + IThread* thrCurrent = ThreadHolder::get()->getThreadAt(iThreads); if (thrCurrent == nullptr) continue; diff --git a/src/sphere/threads.cpp b/src/sphere/threads.cpp index 2749b861b..e8a1473f5 100644 --- a/src/sphere/threads.cpp +++ b/src/sphere/threads.cpp @@ -96,11 +96,12 @@ void IThread::setThreadName(const char* name) /** * ThreadHolder **/ -spherethreadlist_t ThreadHolder::m_threads; -size_t ThreadHolder::m_threadCount = 0; -bool ThreadHolder::m_inited = false; -SimpleMutex ThreadHolder::m_mutex; -TlsValue ThreadHolder::m_currentThread; + +ThreadHolder* ThreadHolder::get() noexcept +{ + static ThreadHolder instance; + return &instance; +} IThread *ThreadHolder::current() noexcept { @@ -234,7 +235,7 @@ void AbstractThread::start() #endif m_terminateEvent.reset(); - ThreadHolder::push(this); + ThreadHolder::get()->push(this); } void AbstractThread::terminate(bool ended) @@ -259,7 +260,7 @@ void AbstractThread::terminate(bool ended) } // Common things - ThreadHolder::pop(this); + ThreadHolder::get()->pop(this); m_id = 0; m_handle = 0; @@ -472,7 +473,7 @@ void AbstractThread::onStart() // a small delay when setting it from AbstractThread::start and it's possible for the id // to not be set fast enough (particular when using pthreads) m_id = getCurrentThreadId(); - ThreadHolder::m_currentThread = this; + ThreadHolder::get()->m_currentThread = this; if (isActive()) // This thread has actually been spawned and the code is executing on a different thread setThreadName(getName()); @@ -704,7 +705,7 @@ void DummySphereThread::tick() StackDebugInformation::StackDebugInformation(const char *name) noexcept { - m_context = static_cast(ThreadHolder::current()); + m_context = static_cast(ThreadHolder::get()->current()); if (m_context != nullptr) { m_context->pushStackCall(name); diff --git a/src/sphere/threads.h b/src/sphere/threads.h index 4ceb377f5..e6b55440f 100644 --- a/src/sphere/threads.h +++ b/src/sphere/threads.h @@ -45,6 +45,96 @@ #define SPHERE_THREADENTRY_CALLTYPE #endif +class IThread; +typedef std::list spherethreadlist_t; + + +// stores a value unique to each thread, intended to hold +// a pointer (e.g. the current IThread instance) +template +class TlsValue +{ +private: +#ifdef _WIN32 + dword _key; +#else + pthread_key_t _key; +#endif + bool _ready; + +public: + TlsValue(); + ~TlsValue(); + +private: + TlsValue(const TlsValue& copy); + TlsValue& operator=(const TlsValue& other); + +public: + // allows assignment to set the current value + TlsValue& operator=(const T& value) + { + set(value); + return *this; + } + + // allows a cast to get current value + operator T() const { return get(); } + +public: + void set(const T value); // set the value for the current thread + T get() const; // get the value for the current thread +}; + +template +TlsValue::TlsValue() +{ + // allocate thread storage +#ifdef _WIN32 + _key = TlsAlloc(); + _ready = (_key != TLS_OUT_OF_INDEXES); +#else + _key = 0; + _ready = (pthread_key_create(&_key, nullptr) == 0); +#endif +} + +template +TlsValue::~TlsValue() +{ + // free the thread storage + if (_ready) +#ifdef _WIN32 + TlsFree(_key); +#else + pthread_key_delete(_key); +#endif + _ready = false; +} + +template +void TlsValue::set(const T value) +{ + ASSERT(_ready); +#ifdef _WIN32 + TlsSetValue(_key, value); +#else + pthread_setspecific(_key, value); +#endif +} + +template +T TlsValue::get() const +{ + if (_ready == false) + return nullptr; +#ifdef _WIN32 + return reinterpret_cast(TlsGetValue(_key)); +#else + return reinterpret_cast(pthread_getspecific(_key)); +#endif +} + // Interface for threads. Almost always should be used instead of any implementing classes class IThread @@ -111,42 +201,38 @@ class IThread virtual ~IThread() { }; }; -typedef std::list spherethreadlist_t; -template -class TlsValue; -// Singleton utility class for working with threads. Holds all running threads inside +// Singleton utility class for working with threads. Holds all running threads inside. class ThreadHolder { + ThreadHolder() = default; + void init(); + public: static constexpr lpctstr m_sClassName = "ThreadHolder"; + static ThreadHolder* get() noexcept; + // returns current working thread or DummySphereThread * if no IThread threads are running - static IThread *current() noexcept; + IThread *current() noexcept; // records a thread to the list. Sould NOT be called, internal usage - static void push(IThread *thread); + void push(IThread *thread); // removes a thread from the list. Sould NOT be called, internal usage - static void pop(IThread *thread); + void pop(IThread *thread); // returns thread at i pos - static IThread * getThreadAt(size_t at); + IThread * getThreadAt(size_t at); // returns number of running threads. Sould NOT be called, unit tests usage - static inline size_t getActiveThreads() { return m_threadCount; } + inline size_t getActiveThreads() noexcept { return m_threadCount; } private: - static void init(); + friend class AbstractThread; + TlsValue m_currentThread; -private: - static spherethreadlist_t m_threads; - static size_t m_threadCount; - static bool m_inited; - static SimpleMutex m_mutex; - -public: - static TlsValue m_currentThread; - -private: - ThreadHolder() = delete; + spherethreadlist_t m_threads; + size_t m_threadCount; + bool m_inited; + SimpleMutex m_mutex; }; // Thread implementation. See IThread for list of available methods. @@ -281,92 +367,6 @@ class DummySphereThread : public AbstractSphereThread virtual void tick(); }; -// stores a value unique to each thread, intended to hold -// a pointer (e.g. the current IThread instance) -template -class TlsValue -{ -private: -#ifdef _WIN32 - dword _key; -#else - pthread_key_t _key; -#endif - bool _ready; - -public: - TlsValue(); - ~TlsValue(); - -private: - TlsValue(const TlsValue& copy); - TlsValue& operator=(const TlsValue& other); - -public: - // allows assignment to set the current value - TlsValue& operator=(const T& value) - { - set(value); - return *this; - } - - // allows a cast to get current value - operator T() const { return get(); } - -public: - void set(const T value); // set the value for the current thread - T get() const; // get the value for the current thread -}; - -template -TlsValue::TlsValue() -{ - // allocate thread storage -#ifdef _WIN32 - _key = TlsAlloc(); - _ready = (_key != TLS_OUT_OF_INDEXES); -#else - _key = 0; - _ready = (pthread_key_create(&_key, nullptr) == 0); -#endif -} - -template -TlsValue::~TlsValue() -{ - // free the thread storage - if (_ready) -#ifdef _WIN32 - TlsFree(_key); -#else - pthread_key_delete(_key); -#endif - _ready = false; -} - -template -void TlsValue::set(const T value) -{ - ASSERT(_ready); -#ifdef _WIN32 - TlsSetValue(_key, value); -#else - pthread_setspecific(_key, value); -#endif -} - -template -T TlsValue::get() const -{ - if (_ready == false) - return nullptr; -#ifdef _WIN32 - return reinterpret_cast(TlsGetValue(_key)); -#else - return reinterpret_cast(pthread_getspecific(_key)); -#endif -} - // used to hold debug information for stack #ifdef THREAD_TRACK_CALLSTACK @@ -386,11 +386,11 @@ class StackDebugInformation public: static void printStackTrace() { - static_cast(ThreadHolder::current())->printStackTrace(); + static_cast(ThreadHolder::get()->current())->printStackTrace(); } static void freezeCallStack(bool freeze) { - static_cast(ThreadHolder::current())->freezeCallStack(freeze); + static_cast(ThreadHolder::get()->current())->freezeCallStack(freeze); } };