00001
00032 #ifndef LL_LLLOCALIDHASHMAP_H
00033 #define LL_LLLOCALIDHASHMAP_H
00034
00035 #include "stdtypes.h"
00036 #include "llerror.h"
00037
00038 const S32 MAX_ITERS = 4;
00039
00040
00041
00042
00043
00044
00045 template <class DATA, int SIZE>
00046 class LLLocalIDHashNode
00047 {
00048 public:
00049 LLLocalIDHashNode();
00050
00051 public:
00052 S32 mCount;
00053 U32 mKey[SIZE];
00054 DATA mData[SIZE];
00055 LLLocalIDHashNode<DATA, SIZE> *mNextNodep;
00056 };
00057
00058
00059
00060
00061
00062 template <class DATA, int SIZE>
00063 LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode()
00064 {
00065 mCount = 0;
00066 mNextNodep = NULL;
00067 }
00068
00069
00070
00071
00072 template <class DATA_TYPE, int SIZE>
00073 class LLLocalIDHashMap;
00074
00075 template <class DATA_TYPE, int SIZE>
00076 class LLLocalIDHashMapIter
00077 {
00078 public:
00079 LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
00080 ~LLLocalIDHashMapIter();
00081
00082 void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
00083 inline void first();
00084 inline void next();
00085 inline DATA_TYPE& current();
00086 inline BOOL done() const;
00087 inline S32 currentBin() const;
00088 inline void setBin(S32 bin);
00089
00090 DATA_TYPE& operator*() const
00091 {
00092 return mCurHashNodep->mData[mCurHashNodeKey];
00093 }
00094 DATA_TYPE* operator->() const
00095 {
00096 return &(operator*());
00097 }
00098
00099 LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
00100 LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
00101
00102 S32 mCurHashMapNodeNum;
00103 S32 mCurHashNodeKey;
00104
00105 DATA_TYPE mNull;
00106
00107 S32 mIterID;
00108 };
00109
00110
00111
00112 template <class DATA_TYPE, int SIZE>
00113 class LLLocalIDHashMap
00114 {
00115 public:
00116 friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>;
00117
00118 LLLocalIDHashMap();
00119
00120
00121 LLLocalIDHashMap(const DATA_TYPE &null_data);
00122
00123
00124 ~LLLocalIDHashMap();
00125
00126 inline DATA_TYPE &get(const U32 local_id);
00127 inline BOOL check(const U32 local_id) const;
00128 inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data);
00129 inline BOOL remove(const U32 local_id);
00130 void removeAll();
00131
00132 void setNull(const DATA_TYPE data) { mNull = data; }
00133
00134 inline S32 getLength() const;
00135
00136 void dumpIter();
00137 void dumpBin(U32 bin);
00138
00139 protected:
00140
00141 void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
00142 void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
00143
00144
00145
00146 BOOL removeWithShift(const U32 local_id);
00147
00148 protected:
00149 LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256];
00150
00151 S32 mIterCount;
00152 LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS];
00153
00154 DATA_TYPE mNull;
00155 };
00156
00157
00158
00159
00160
00161
00162 template <class DATA_TYPE, int SIZE>
00163 LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap()
00164 : mIterCount(0),
00165 mNull()
00166 {
00167 S32 i;
00168 for (i = 0; i < MAX_ITERS; i++)
00169 {
00170 mIters[i] = NULL;
00171 }
00172 }
00173
00174 template <class DATA_TYPE, int SIZE>
00175 LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data)
00176 : mIterCount(0),
00177 mNull(null_data)
00178 {
00179 S32 i;
00180 for (i = 0; i < MAX_ITERS; i++)
00181 {
00182 mIters[i] = NULL;
00183 }
00184 }
00185
00186 template <class DATA_TYPE, int SIZE>
00187 LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap()
00188 {
00189 S32 i;
00190 for (i = 0; i < MAX_ITERS; i++)
00191 {
00192 if (mIters[i])
00193 {
00194 mIters[i]->mHashMapp = NULL;
00195 mIterCount--;
00196 }
00197 }
00198 removeAll();
00199 }
00200
00201 template <class DATA_TYPE, int SIZE>
00202 void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll()
00203 {
00204 S32 bin;
00205 for (bin = 0; bin < 256; bin++)
00206 {
00207 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00208
00209 BOOL first = TRUE;
00210 do
00211 {
00212 S32 i;
00213 const S32 count = nodep->mCount;
00214
00215
00216 for (i = 0; i < count; i++)
00217 {
00218 nodep->mData[i] = mNull;
00219 }
00220
00221 nodep->mCount = 0;
00222
00223
00224 LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
00225 nodep = nodep->mNextNodep;
00226
00227
00228 if (first)
00229 {
00230 first = FALSE;
00231 curp->mNextNodep = NULL;
00232 }
00233 else
00234 {
00235 delete curp;
00236 }
00237 } while (nodep);
00238 }
00239 }
00240
00241 template <class DATA_TYPE, int SIZE>
00242 void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter()
00243 {
00244 std::cout << "Hash map with " << mIterCount << " iterators" << std::endl;
00245
00246 std::cout << "Hash Map Iterators:" << std::endl;
00247 S32 i;
00248 for (i = 0; i < MAX_ITERS; i++)
00249 {
00250 if (mIters[i])
00251 {
00252 llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl;
00253 }
00254 else
00255 {
00256 llinfos << i << "null" << llendl;
00257 }
00258 }
00259 }
00260
00261 template <class DATA_TYPE, int SIZE>
00262 void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin)
00263 {
00264 std::cout << "Dump bin " << bin << std::endl;
00265
00266 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00267 S32 node = 0;
00268 do
00269 {
00270 std::cout << "Bin " << bin
00271 << " node " << node
00272 << " count " << nodep->mCount
00273 << " contains " << std::flush;
00274
00275 S32 i;
00276 for (i = 0; i < nodep->mCount; i++)
00277 {
00278 std::cout << nodep->mData[i] << " " << std::flush;
00279 }
00280
00281 std::cout << std::endl;
00282
00283 nodep = nodep->mNextNodep;
00284 node++;
00285 } while (nodep);
00286 }
00287
00288 template <class DATA_TYPE, int SIZE>
00289 inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const
00290 {
00291 S32 count = 0;
00292 S32 bin;
00293 for (bin = 0; bin < 256; bin++)
00294 {
00295 const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
00296 while (nodep)
00297 {
00298 count += nodep->mCount;
00299 nodep = nodep->mNextNodep;
00300 }
00301 }
00302 return count;
00303 }
00304
00305 template <class DATA_TYPE, int SIZE>
00306 inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id)
00307 {
00308 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00309
00310 do
00311 {
00312 S32 i;
00313 const S32 count = nodep->mCount;
00314
00315
00316 for (i = 0; i < count; i++)
00317 {
00318 if (nodep->mKey[i] == local_id)
00319 {
00320
00321 return nodep->mData[i];
00322 }
00323 }
00324
00325
00326 nodep = nodep->mNextNodep;
00327 } while (nodep);
00328
00329 return mNull;
00330 }
00331
00332
00333 template <class DATA_TYPE, int SIZE>
00334 inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const
00335 {
00336 const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00337
00338 do
00339 {
00340 S32 i;
00341 const S32 count = nodep->mCount;
00342
00343
00344 for (i = 0; i < count; i++)
00345 {
00346 if (nodep->mKey[i] == local_id)
00347 {
00348
00349 return TRUE;
00350 }
00351 }
00352
00353
00354 nodep = nodep->mNextNodep;
00355 } while (nodep);
00356
00357
00358 return FALSE;
00359 }
00360
00361
00362 template <class DATA_TYPE, int SIZE>
00363 inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data)
00364 {
00365
00366
00367
00368
00369 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
00370
00371 while (1)
00372 {
00373 const S32 count = nodep->mCount;
00374
00375 S32 i;
00376 for (i = 0; i < count; i++)
00377 {
00378 if (nodep->mKey[i] == local_id)
00379 {
00380
00381
00382 nodep->mData[i] = data;
00383 return nodep->mData[i];
00384 }
00385 }
00386 if (!nodep->mNextNodep)
00387 {
00388
00389 if (i < SIZE)
00390 {
00391
00392
00393 nodep->mKey[i] = local_id;
00394 nodep->mData[i] = data;
00395 nodep->mCount++;
00396
00397 return nodep->mData[i];
00398 }
00399 else
00400 {
00401
00402 nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>;
00403 nodep->mNextNodep->mKey[0] = local_id;
00404 nodep->mNextNodep->mData[0] = data;
00405 nodep->mNextNodep->mCount = 1;
00406
00407 return nodep->mNextNodep->mData[0];
00408 }
00409 }
00410
00411
00412 nodep = nodep->mNextNodep;
00413 }
00414 }
00415
00416
00417 template <class DATA_TYPE, int SIZE>
00418 inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id)
00419 {
00420
00421
00422
00423
00424
00425
00426 const S32 node_index = local_id & 0xff;
00427
00428 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
00429
00430
00431 do
00432 {
00433 const S32 count = nodep->mCount;
00434
00435 S32 i;
00436 for (i = 0; i < count; i++)
00437 {
00438 if (nodep->mKey[i] == local_id)
00439 {
00440
00441
00442
00443
00444
00445
00446 BOOL need_shift = FALSE;
00447 S32 cur_iter;
00448 if (mIterCount)
00449 {
00450 for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
00451 {
00452 if (mIters[cur_iter])
00453 {
00454
00455
00456
00457
00458 if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
00459 {
00460 if ((mIters[cur_iter]->mCurHashNodep == nodep)
00461 && (mIters[cur_iter]->mCurHashNodeKey == i))
00462 {
00463
00464
00465 }
00466 else
00467 {
00468
00469
00470
00471
00472 need_shift = TRUE;
00473 }
00474 }
00475 }
00476 }
00477 }
00478
00479
00480 if (need_shift)
00481 {
00482 return removeWithShift(local_id);
00483 }
00484
00485
00486
00487 for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
00488 {
00489 if (mIters[cur_iter])
00490 {
00491
00492
00493
00494
00495 if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
00496 {
00497 if ((mIters[cur_iter]->mCurHashNodep == nodep)
00498 && (mIters[cur_iter]->mCurHashNodeKey == i))
00499 {
00500
00501
00502 if (nodep->mCount > 1)
00503 {
00504
00505
00506 mIters[cur_iter]->mCurHashNodeKey--;
00507 }
00508 else
00509 {
00510
00511
00512
00513
00514 mIters[cur_iter]->next();
00515 mIters[cur_iter]->mCurHashNodeKey--;
00516 }
00517 }
00518 }
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527 LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index];
00528 LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
00529
00530
00531 while (lastp->mNextNodep)
00532 {
00533 prevp = lastp;
00534 lastp = lastp->mNextNodep;
00535 }
00536
00537
00538 nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
00539 nodep->mData[i] = lastp->mData[lastp->mCount - 1];
00540
00541
00542 lastp->mCount--;
00543 lastp->mData[lastp->mCount] = mNull;
00544
00545 if (!lastp->mCount)
00546 {
00547
00548 if (lastp != &mNodes[local_id & 0xff])
00549 {
00550
00551
00552
00553 prevp->mNextNodep = NULL;
00554 delete lastp;
00555 }
00556 }
00557
00558 return TRUE;
00559 }
00560 }
00561
00562
00563 nodep = nodep->mNextNodep;
00564 } while (nodep);
00565
00566 return FALSE;
00567 }
00568
00569 template <class DATA_TYPE, int SIZE>
00570 BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id)
00571 {
00572 const S32 node_index = local_id & 0xFF;
00573 LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
00574 LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL;
00575 BOOL found = FALSE;
00576
00577 do
00578 {
00579 const S32 count = nodep->mCount;
00580 S32 i;
00581 for (i = 0; i < count; i++)
00582 {
00583 if (nodep->mKey[i] == local_id)
00584 {
00585
00586
00587 found = TRUE;
00588 }
00589
00590 if (found)
00591 {
00592
00593
00594 S32 cur_iter;
00595 for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++)
00596 {
00597 LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter;
00598 iter = mIters[cur_iter];
00599
00600 if (iter
00601 && iter->mCurHashMapNodeNum == node_index
00602 && iter->mCurHashNodep == nodep
00603 && iter->mCurHashNodeKey == i)
00604 {
00605 if (i > 0)
00606 {
00607
00608
00609 iter->mCurHashNodeKey--;
00610 }
00611 else if (prevp)
00612 {
00613
00614 iter->mCurHashNodep = prevp;
00615 iter->mCurHashNodeKey = prevp->mCount - 1;
00616 }
00617 else
00618 {
00619
00620
00621
00622
00623
00624
00625 iter->mCurHashNodeKey = -1;
00626 }
00627 }
00628 }
00629
00630
00631 if (i < count-1)
00632 {
00633
00634
00635 nodep->mKey[i] = nodep->mKey[i+1];
00636 nodep->mData[i] = nodep->mData[i+1];
00637 }
00638 else if (nodep->mNextNodep)
00639 {
00640
00641
00642 nodep->mKey[i] = nodep->mNextNodep->mKey[0];
00643 nodep->mData[i] = nodep->mNextNodep->mData[0];
00644 }
00645 else
00646 {
00647
00648
00649 nodep->mKey[i] = 0;
00650 nodep->mData[i] = mNull;
00651 }
00652 }
00653 }
00654
00655
00656 if (found
00657 && !nodep->mNextNodep)
00658 {
00659
00660 nodep->mCount--;
00661
00662 if (nodep->mCount == 0)
00663 {
00664
00665 if (nodep != &mNodes[node_index])
00666 {
00667
00668 llassert(prevp);
00669
00670
00671
00672
00673 prevp->mNextNodep = NULL;
00674 delete nodep;
00675 nodep = NULL;
00676 }
00677 }
00678
00679
00680 return found;
00681 }
00682
00683 prevp = nodep;
00684 nodep = nodep->mNextNodep;
00685 } while (nodep);
00686
00687 return found;
00688 }
00689
00690 template <class DATA_TYPE, int SIZE>
00691 void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
00692 {
00693 S32 i;
00694 for (i = 0; i < MAX_ITERS; i++)
00695 {
00696 if (mIters[i] == iter)
00697 {
00698 mIters[i] = NULL;
00699 mIterCount--;
00700 return;
00701 }
00702 }
00703 llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl;
00704 }
00705
00706 template <class DATA_TYPE, int SIZE>
00707 void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
00708 {
00709 S32 i;
00710 for (i = 0; i < MAX_ITERS; i++)
00711 {
00712 if (mIters[i] == NULL)
00713 {
00714 mIters[i] = iter;
00715 mIterCount++;
00716 return;
00717 }
00718 }
00719 llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl;
00720 }
00721
00722
00723
00724
00725
00726
00727 template <class DATA_TYPE, int SIZE>
00728 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
00729 {
00730 mHashMapp = NULL;
00731 setMap(hash_mapp);
00732 }
00733
00734 template <class DATA_TYPE, int SIZE>
00735 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter()
00736 {
00737 if (mHashMapp)
00738 {
00739 mHashMapp->removeIter(this);
00740 }
00741 }
00742
00743 template <class DATA_TYPE, int SIZE>
00744 void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
00745 {
00746 if (mHashMapp)
00747 {
00748 mHashMapp->removeIter(this);
00749 }
00750 mHashMapp = hash_mapp;
00751 if (mHashMapp)
00752 {
00753 mHashMapp->addIter(this);
00754 }
00755
00756 mCurHashNodep = NULL;
00757 mCurHashMapNodeNum = -1;
00758 mCurHashNodeKey = 0;
00759 }
00760
00761 template <class DATA_TYPE, int SIZE>
00762 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first()
00763 {
00764
00765 S32 i;
00766 for (i = 0; i < 256; i++)
00767 {
00768 if (mHashMapp->mNodes[i].mCount)
00769 {
00770
00771 mCurHashNodep = &mHashMapp->mNodes[i];
00772 mCurHashMapNodeNum = i;
00773 mCurHashNodeKey = 0;
00774
00775 return;
00776 }
00777 }
00778
00779
00780 mCurHashNodep = NULL;
00781
00782 return;
00783 }
00784
00785 template <class DATA_TYPE, int SIZE>
00786 inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const
00787 {
00788 return mCurHashNodep ? FALSE : TRUE;
00789 }
00790
00791 template <class DATA_TYPE, int SIZE>
00792 inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const
00793 {
00794 if ( (mCurHashMapNodeNum > 255)
00795 ||(mCurHashMapNodeNum < 0))
00796 {
00797 return 0;
00798 }
00799 else
00800 {
00801 return mCurHashMapNodeNum;
00802 }
00803 }
00804
00805 template <class DATA_TYPE, int SIZE>
00806 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin)
00807 {
00808
00809 S32 i;
00810 bin = llclamp(bin, 0, 255);
00811 for (i = bin; i < 256; i++)
00812 {
00813 if (mHashMapp->mNodes[i].mCount)
00814 {
00815
00816 mCurHashNodep = &mHashMapp->mNodes[i];
00817 mCurHashMapNodeNum = i;
00818 mCurHashNodeKey = 0;
00819 return;
00820 }
00821 }
00822 for (i = 0; i < bin; i++)
00823 {
00824 if (mHashMapp->mNodes[i].mCount)
00825 {
00826
00827 mCurHashNodep = &mHashMapp->mNodes[i];
00828 mCurHashMapNodeNum = i;
00829 mCurHashNodeKey = 0;
00830 return;
00831 }
00832 }
00833
00834 mCurHashNodep = NULL;
00835 }
00836
00837 template <class DATA_TYPE, int SIZE>
00838 inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current()
00839 {
00840 if (!mCurHashNodep)
00841 {
00842 return mNull;
00843 }
00844 return mCurHashNodep->mData[mCurHashNodeKey];
00845 }
00846
00847 template <class DATA_TYPE, int SIZE>
00848 inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next()
00849 {
00850
00851 if (!mCurHashNodep)
00852 {
00853
00854 return;
00855 }
00856
00857
00858 mCurHashNodeKey++;
00859 if (mCurHashNodeKey < mCurHashNodep->mCount)
00860 {
00861
00862
00863 return;
00864 }
00865
00866
00867 mCurHashNodep = mCurHashNodep->mNextNodep;
00868 if (mCurHashNodep)
00869 {
00870
00871 mCurHashNodeKey = 0;
00872
00873 return;
00874 }
00875
00876
00877 mCurHashMapNodeNum++;
00878
00879 S32 i;
00880 for (i = mCurHashMapNodeNum; i < 256; i++)
00881 {
00882 if (mHashMapp->mNodes[i].mCount)
00883 {
00884
00885 mCurHashNodep = &mHashMapp->mNodes[i];
00886 mCurHashMapNodeNum = i;
00887 mCurHashNodeKey = 0;
00888
00889 return;
00890 }
00891 }
00892
00893
00894 mCurHashNodep = NULL;
00895 mHashMapp->mIterCount--;
00896
00897 return;
00898 }
00899
00900 #endif // LL_LLLOCALIDHASHMAP_H