simDictionary.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "console/simDictionary.h"
  23. #include "console/simBase.h"
  24. //----------------------------------------------------------------------------
  25. //----------------------------------------------------------------------------
  26. extern U32 HashPointer(StringTableEntry e);
  27. SimNameDictionary::SimNameDictionary()
  28. {
  29. #ifndef USE_NEW_SIMDICTIONARY
  30. hashTable = NULL;
  31. hashTableSize = DefaultTableSize;
  32. hashEntryCount = 0;
  33. #endif
  34. mutex = Mutex::createMutex();
  35. }
  36. SimNameDictionary::~SimNameDictionary()
  37. {
  38. #ifndef USE_NEW_SIMDICTIONARY
  39. delete[] hashTable;
  40. #endif
  41. Mutex::destroyMutex(mutex);
  42. }
  43. void SimNameDictionary::insert(SimObject* obj)
  44. {
  45. if (!obj || !obj->getName())
  46. return;
  47. SimObject* checkForDup = find(obj->getName());
  48. if (checkForDup)
  49. Con::warnf("Warning! You have a duplicate object name of %s. This can cause problems. You should rename one of them.", obj->getName());
  50. Mutex::lockMutex(mutex);
  51. #ifndef USE_NEW_SIMDICTIONARY
  52. if (!hashTable)
  53. {
  54. hashTable = new SimObject *[DefaultTableSize];
  55. hashTableSize = DefaultTableSize;
  56. hashEntryCount = 0;
  57. dMemset(hashTable, 0, sizeof(*hashTable) * DefaultTableSize);
  58. }
  59. S32 idx = HashPointer(obj->getName()) % hashTableSize;
  60. obj->nextNameObject = hashTable[idx];
  61. hashTable[idx] = obj;
  62. hashEntryCount++;
  63. // Rehash if necessary.
  64. if (hashEntryCount > hashTableSize)
  65. {
  66. // Allocate new table.
  67. U32 newHashTableSize = hashTableSize * 2 + 1;
  68. SimObject** newHashTable = new SimObject *[newHashTableSize];
  69. dMemset(newHashTable, 0, sizeof(newHashTable[0]) * newHashTableSize);
  70. // Move entries over.
  71. for (U32 i = 0; i < hashTableSize; ++i)
  72. for (SimObject* object = hashTable[i]; object != NULL; )
  73. {
  74. SimObject* next = object->nextNameObject;
  75. idx = HashPointer(object->getName()) % newHashTableSize;
  76. object->nextNameObject = newHashTable[idx];
  77. newHashTable[idx] = object;
  78. object = next;
  79. }
  80. // Switch tables.
  81. delete[] hashTable;
  82. hashTable = newHashTable;
  83. hashTableSize = newHashTableSize;
  84. }
  85. #else
  86. root[obj->objectName] = obj;
  87. #endif
  88. Mutex::unlockMutex(mutex);
  89. }
  90. SimObject* SimNameDictionary::find(StringTableEntry name)
  91. {
  92. #ifndef USE_NEW_SIMDICTIONARY
  93. // NULL is a valid lookup - it will always return NULL
  94. if (!hashTable)
  95. return NULL;
  96. Mutex::lockMutex(mutex);
  97. S32 idx = HashPointer(name) % hashTableSize;
  98. SimObject *walk = hashTable[idx];
  99. while (walk)
  100. {
  101. if (walk->getName() == name)
  102. {
  103. Mutex::unlockMutex(mutex);
  104. return walk;
  105. }
  106. walk = walk->nextNameObject;
  107. }
  108. Mutex::unlockMutex(mutex);
  109. return NULL;
  110. #else
  111. Mutex::lockMutex(mutex);
  112. StringDictDef::iterator it = root.find(name);
  113. SimObject* f = (it == root.end() ? NULL : it->second);
  114. Mutex::unlockMutex(mutex);
  115. return f;
  116. #endif
  117. }
  118. void SimNameDictionary::remove(SimObject* obj)
  119. {
  120. if (!obj || !obj->getName())
  121. return;
  122. Mutex::lockMutex(mutex);
  123. #ifndef USE_NEW_SIMDICTIONARY
  124. SimObject **walk = &hashTable[HashPointer(obj->getName()) % hashTableSize];
  125. while (*walk)
  126. {
  127. if (*walk == obj)
  128. {
  129. *walk = obj->nextNameObject;
  130. obj->nextNameObject = nullptr;
  131. hashEntryCount--;
  132. Mutex::unlockMutex(mutex);
  133. return;
  134. }
  135. walk = &((*walk)->nextNameObject);
  136. }
  137. #else
  138. const char* name = obj->objectName;
  139. if (root.find(name) != root.end())
  140. root.erase(name);
  141. #endif
  142. Mutex::unlockMutex(mutex);
  143. }
  144. //----------------------------------------------------------------------------
  145. SimManagerNameDictionary::SimManagerNameDictionary()
  146. {
  147. #ifndef USE_NEW_SIMDICTIONARY
  148. hashTable = new SimObject *[DefaultTableSize];
  149. hashTableSize = DefaultTableSize;
  150. hashEntryCount = 0;
  151. dMemset(hashTable, 0, sizeof(hashTable[0]) * hashTableSize);
  152. #endif
  153. mutex = Mutex::createMutex();
  154. }
  155. SimManagerNameDictionary::~SimManagerNameDictionary()
  156. {
  157. #ifndef USE_NEW_SIMDICTIONARY
  158. delete[] hashTable;
  159. #endif
  160. Mutex::destroyMutex(mutex);
  161. }
  162. void SimManagerNameDictionary::insert(SimObject* obj)
  163. {
  164. if (!obj || !obj->getName())
  165. return;
  166. Mutex::lockMutex(mutex);
  167. #ifndef USE_NEW_SIMDICTIONARY
  168. S32 idx = HashPointer(obj->getName()) % hashTableSize;
  169. obj->nextManagerNameObject = hashTable[idx];
  170. hashTable[idx] = obj;
  171. hashEntryCount++;
  172. // Rehash if necessary.
  173. if (hashEntryCount > hashTableSize)
  174. {
  175. // Allocate new table.
  176. U32 newHashTableSize = hashTableSize * 2 + 1;
  177. SimObject** newHashTable = new SimObject *[newHashTableSize];
  178. dMemset(newHashTable, 0, sizeof(newHashTable[0]) * newHashTableSize);
  179. // Move entries over.
  180. for (U32 i = 0; i < hashTableSize; ++i)
  181. for (SimObject* object = hashTable[i]; object != NULL; )
  182. {
  183. SimObject* next = object->nextManagerNameObject;
  184. idx = HashPointer(object->getName()) % newHashTableSize;
  185. object->nextManagerNameObject = newHashTable[idx];
  186. newHashTable[idx] = object;
  187. object = next;
  188. }
  189. // Switch tables.
  190. delete[] hashTable;
  191. hashTable = newHashTable;
  192. hashTableSize = newHashTableSize;
  193. }
  194. #else
  195. root[obj->objectName] = obj;
  196. #endif
  197. Mutex::unlockMutex(mutex);
  198. }
  199. SimObject* SimManagerNameDictionary::find(StringTableEntry name)
  200. {
  201. // NULL is a valid lookup - it will always return NULL
  202. Mutex::lockMutex(mutex);
  203. #ifndef USE_NEW_SIMDICTIONARY
  204. S32 idx = HashPointer(name) % hashTableSize;
  205. SimObject *walk = hashTable[idx];
  206. while (walk)
  207. {
  208. if (walk->getName() == name)
  209. {
  210. Mutex::unlockMutex(mutex);
  211. return walk;
  212. }
  213. walk = walk->nextManagerNameObject;
  214. }
  215. Mutex::unlockMutex(mutex);
  216. return NULL;
  217. #else
  218. StringDictDef::iterator it = root.find(name);
  219. SimObject* f = (it == root.end() ? NULL : it->second);
  220. Mutex::unlockMutex(mutex);
  221. return f;
  222. #endif
  223. }
  224. void SimManagerNameDictionary::remove(SimObject* obj)
  225. {
  226. if (!obj || !obj->getName())
  227. return;
  228. #ifndef USE_NEW_SIMDICTIONARY
  229. Mutex::lockMutex(mutex);
  230. SimObject **walk = &hashTable[HashPointer(obj->getName()) % hashTableSize];
  231. while (*walk)
  232. {
  233. if (*walk == obj)
  234. {
  235. *walk = obj->nextManagerNameObject;
  236. obj->nextManagerNameObject = nullptr;
  237. hashEntryCount--;
  238. Mutex::unlockMutex(mutex);
  239. return;
  240. }
  241. walk = &((*walk)->nextManagerNameObject);
  242. }
  243. #else
  244. StringTableEntry name = obj->objectName;
  245. if (root.find(name) != root.end())
  246. root.erase(name);
  247. #endif
  248. Mutex::unlockMutex(mutex);
  249. }
  250. //---------------------------------------------------------------------------
  251. //---------------------------------------------------------------------------
  252. SimIdDictionary::SimIdDictionary()
  253. {
  254. #ifndef USE_NEW_SIMDICTIONARY
  255. dMemset(table, 0, sizeof(table[0]) * DefaultTableSize);
  256. #endif
  257. mutex = Mutex::createMutex();
  258. }
  259. SimIdDictionary::~SimIdDictionary()
  260. {
  261. Mutex::destroyMutex(mutex);
  262. }
  263. void SimIdDictionary::insert(SimObject* obj)
  264. {
  265. if (!obj)
  266. return;
  267. Mutex::lockMutex(mutex);
  268. #ifndef USE_NEW_SIMDICTIONARY
  269. S32 idx = obj->getId() & TableBitMask;
  270. obj->nextIdObject = table[idx];
  271. AssertFatal(obj->nextIdObject != obj, "SimIdDictionary::insert - Creating Infinite Loop linking to self!");
  272. table[idx] = obj;
  273. #else
  274. root[obj->getId()] = obj;
  275. #endif
  276. Mutex::unlockMutex(mutex);
  277. }
  278. SimObject* SimIdDictionary::find(S32 id)
  279. {
  280. Mutex::lockMutex(mutex);
  281. #ifndef USE_NEW_SIMDICTIONARY
  282. S32 idx = id & TableBitMask;
  283. SimObject *walk = table[idx];
  284. while (walk)
  285. {
  286. if (walk->getId() == U32(id))
  287. {
  288. Mutex::unlockMutex(mutex);
  289. return walk;
  290. }
  291. walk = walk->nextIdObject;
  292. }
  293. Mutex::unlockMutex(mutex);
  294. return NULL;
  295. #else
  296. SimObjectIdDictDef::iterator it = root.find(id);
  297. SimObject* f = (it == root.end() ? NULL : it->second);
  298. Mutex::unlockMutex(mutex);
  299. return f;
  300. #endif
  301. }
  302. void SimIdDictionary::remove(SimObject* obj)
  303. {
  304. if (!obj)
  305. return;
  306. Mutex::lockMutex(mutex);
  307. #ifndef USE_NEW_SIMDICTIONARY
  308. SimObject **walk = &table[obj->getId() & TableBitMask];
  309. while (*walk && *walk != obj)
  310. walk = &((*walk)->nextIdObject);
  311. if (*walk)
  312. *walk = obj->nextIdObject;
  313. #else
  314. root.erase(obj->getId());
  315. #endif
  316. Mutex::unlockMutex(mutex);
  317. }
  318. //---------------------------------------------------------------------------
  319. //---------------------------------------------------------------------------