//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "console/simDictionary.h" #include "console/simBase.h" //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- extern U32 HashPointer(StringTableEntry e); SimNameDictionary::SimNameDictionary() { #ifndef USE_NEW_SIMDICTIONARY hashTable = NULL; hashTableSize = DefaultTableSize; hashEntryCount = 0; #endif mutex = Mutex::createMutex(); } SimNameDictionary::~SimNameDictionary() { #ifndef USE_NEW_SIMDICTIONARY delete[] hashTable; #endif Mutex::destroyMutex(mutex); } void SimNameDictionary::insert(SimObject* obj) { if (!obj || !obj->getName()) return; SimObject* checkForDup = find(obj->getName()); if (checkForDup) Con::warnf("Warning! You have a duplicate object name of %s. This can cause problems. You should rename one of them.", obj->getName()); Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY if (!hashTable) { hashTable = new SimObject *[DefaultTableSize]; hashTableSize = DefaultTableSize; hashEntryCount = 0; dMemset(hashTable, 0, sizeof(*hashTable) * DefaultTableSize); } S32 idx = HashPointer(obj->getName()) % hashTableSize; obj->nextNameObject = hashTable[idx]; hashTable[idx] = obj; hashEntryCount++; // Rehash if necessary. if (hashEntryCount > hashTableSize) { // Allocate new table. U32 newHashTableSize = hashTableSize * 2 + 1; SimObject** newHashTable = new SimObject *[newHashTableSize]; dMemset(newHashTable, 0, sizeof(newHashTable[0]) * newHashTableSize); // Move entries over. for (U32 i = 0; i < hashTableSize; ++i) for (SimObject* object = hashTable[i]; object != NULL; ) { SimObject* next = object->nextNameObject; idx = HashPointer(object->getName()) % newHashTableSize; object->nextNameObject = newHashTable[idx]; newHashTable[idx] = object; object = next; } // Switch tables. delete[] hashTable; hashTable = newHashTable; hashTableSize = newHashTableSize; } #else root[obj->objectName] = obj; #endif Mutex::unlockMutex(mutex); } SimObject* SimNameDictionary::find(StringTableEntry name) { #ifndef USE_NEW_SIMDICTIONARY // NULL is a valid lookup - it will always return NULL if (!hashTable) return NULL; Mutex::lockMutex(mutex); S32 idx = HashPointer(name) % hashTableSize; SimObject *walk = hashTable[idx]; while (walk) { if (walk->getName() == name) { Mutex::unlockMutex(mutex); return walk; } walk = walk->nextNameObject; } Mutex::unlockMutex(mutex); return NULL; #else Mutex::lockMutex(mutex); StringDictDef::iterator it = root.find(name); SimObject* f = (it == root.end() ? NULL : it->second); Mutex::unlockMutex(mutex); return f; #endif } void SimNameDictionary::remove(SimObject* obj) { if (!obj || !obj->getName()) return; Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY SimObject **walk = &hashTable[HashPointer(obj->getName()) % hashTableSize]; while (*walk) { if (*walk == obj) { *walk = obj->nextNameObject; obj->nextNameObject = nullptr; hashEntryCount--; Mutex::unlockMutex(mutex); return; } walk = &((*walk)->nextNameObject); } #else const char* name = obj->objectName; if (root.find(name) != root.end()) root.erase(name); #endif Mutex::unlockMutex(mutex); } //---------------------------------------------------------------------------- SimManagerNameDictionary::SimManagerNameDictionary() { #ifndef USE_NEW_SIMDICTIONARY hashTable = new SimObject *[DefaultTableSize]; hashTableSize = DefaultTableSize; hashEntryCount = 0; dMemset(hashTable, 0, sizeof(hashTable[0]) * hashTableSize); #endif mutex = Mutex::createMutex(); } SimManagerNameDictionary::~SimManagerNameDictionary() { #ifndef USE_NEW_SIMDICTIONARY delete[] hashTable; #endif Mutex::destroyMutex(mutex); } void SimManagerNameDictionary::insert(SimObject* obj) { if (!obj || !obj->getName()) return; Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY S32 idx = HashPointer(obj->getName()) % hashTableSize; obj->nextManagerNameObject = hashTable[idx]; hashTable[idx] = obj; hashEntryCount++; // Rehash if necessary. if (hashEntryCount > hashTableSize) { // Allocate new table. U32 newHashTableSize = hashTableSize * 2 + 1; SimObject** newHashTable = new SimObject *[newHashTableSize]; dMemset(newHashTable, 0, sizeof(newHashTable[0]) * newHashTableSize); // Move entries over. for (U32 i = 0; i < hashTableSize; ++i) for (SimObject* object = hashTable[i]; object != NULL; ) { SimObject* next = object->nextManagerNameObject; idx = HashPointer(object->getName()) % newHashTableSize; object->nextManagerNameObject = newHashTable[idx]; newHashTable[idx] = object; object = next; } // Switch tables. delete[] hashTable; hashTable = newHashTable; hashTableSize = newHashTableSize; } #else root[obj->objectName] = obj; #endif Mutex::unlockMutex(mutex); } SimObject* SimManagerNameDictionary::find(StringTableEntry name) { // NULL is a valid lookup - it will always return NULL Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY S32 idx = HashPointer(name) % hashTableSize; SimObject *walk = hashTable[idx]; while (walk) { if (walk->getName() == name) { Mutex::unlockMutex(mutex); return walk; } walk = walk->nextManagerNameObject; } Mutex::unlockMutex(mutex); return NULL; #else StringDictDef::iterator it = root.find(name); SimObject* f = (it == root.end() ? NULL : it->second); Mutex::unlockMutex(mutex); return f; #endif } void SimManagerNameDictionary::remove(SimObject* obj) { if (!obj || !obj->getName()) return; #ifndef USE_NEW_SIMDICTIONARY Mutex::lockMutex(mutex); SimObject **walk = &hashTable[HashPointer(obj->getName()) % hashTableSize]; while (*walk) { if (*walk == obj) { *walk = obj->nextManagerNameObject; obj->nextManagerNameObject = nullptr; hashEntryCount--; Mutex::unlockMutex(mutex); return; } walk = &((*walk)->nextManagerNameObject); } #else StringTableEntry name = obj->objectName; if (root.find(name) != root.end()) root.erase(name); #endif Mutex::unlockMutex(mutex); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- SimIdDictionary::SimIdDictionary() { #ifndef USE_NEW_SIMDICTIONARY dMemset(table, 0, sizeof(table[0]) * DefaultTableSize); #endif mutex = Mutex::createMutex(); } SimIdDictionary::~SimIdDictionary() { Mutex::destroyMutex(mutex); } void SimIdDictionary::insert(SimObject* obj) { if (!obj) return; Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY S32 idx = obj->getId() & TableBitMask; obj->nextIdObject = table[idx]; AssertFatal(obj->nextIdObject != obj, "SimIdDictionary::insert - Creating Infinite Loop linking to self!"); table[idx] = obj; #else root[obj->getId()] = obj; #endif Mutex::unlockMutex(mutex); } SimObject* SimIdDictionary::find(S32 id) { Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY S32 idx = id & TableBitMask; SimObject *walk = table[idx]; while (walk) { if (walk->getId() == U32(id)) { Mutex::unlockMutex(mutex); return walk; } walk = walk->nextIdObject; } Mutex::unlockMutex(mutex); return NULL; #else SimObjectIdDictDef::iterator it = root.find(id); SimObject* f = (it == root.end() ? NULL : it->second); Mutex::unlockMutex(mutex); return f; #endif } void SimIdDictionary::remove(SimObject* obj) { if (!obj) return; Mutex::lockMutex(mutex); #ifndef USE_NEW_SIMDICTIONARY SimObject **walk = &table[obj->getId() & TableBitMask]; while (*walk && *walk != obj) walk = &((*walk)->nextIdObject); if (*walk) *walk = obj->nextIdObject; #else root.erase(obj->getId()); #endif Mutex::unlockMutex(mutex); } //--------------------------------------------------------------------------- //---------------------------------------------------------------------------