PageRenderTime 20ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/llptrskiplist.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 724 lines | 526 code | 91 blank | 107 comment | 66 complexity | 6bd260067a69c0501f3a22032cd194b3 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llptrskiplist.h
  3. * @brief Skip list implementation.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #ifndef LL_LLPTRSKIPLIST_H
  27. #define LL_LLPTRSKIPLIST_H
  28. #include "llerror.h"
  29. #include "llrand.h"
  30. //#include "vmath.h"
  31. #include "llrand.h"
  32. /////////////////////////////////////////////
  33. //
  34. // LLPtrSkipList implementation - skip list for pointers to objects
  35. //
  36. template <class DATA_TYPE, S32 BINARY_DEPTH = 8>
  37. class LLPtrSkipList
  38. {
  39. public:
  40. friend class LLPtrSkipNode;
  41. // basic constructor
  42. LLPtrSkipList();
  43. // basic constructor including sorter
  44. LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second),
  45. BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second));
  46. ~LLPtrSkipList();
  47. inline void setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second));
  48. inline void setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second));
  49. inline BOOL addData(DATA_TYPE *data);
  50. inline BOOL checkData(const DATA_TYPE *data);
  51. inline S32 getLength(); // returns number of items in the list - NOT constant time!
  52. inline BOOL removeData(const DATA_TYPE *data);
  53. // note that b_sort is ignored
  54. inline BOOL moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort);
  55. inline BOOL moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort);
  56. // resort -- use when the value we're sorting by changes
  57. /* IW 12/6/02 - This doesn't work!
  58. Instead, remove the data BEFORE you change it
  59. Then re-insert it after you change it
  60. BOOL resortData(DATA_TYPE *data)
  61. */
  62. // remove all nodes from the list but do not delete data
  63. inline void removeAllNodes();
  64. inline BOOL deleteData(const DATA_TYPE *data);
  65. // remove all nodes from the list and delete data
  66. inline void deleteAllData();
  67. // place mCurrentp on first node
  68. inline void resetList();
  69. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  70. inline DATA_TYPE *getCurrentData();
  71. // same as getCurrentData() but a more intuitive name for the operation
  72. inline DATA_TYPE *getNextData();
  73. // remove the Node at mCurentOperatingp
  74. // leave mCurrentp and mCurentOperatingp on the next entry
  75. inline void removeCurrentData();
  76. // delete the Node at mCurentOperatingp
  77. // leave mCurrentp and mCurentOperatingp on the next entry
  78. inline void deleteCurrentData();
  79. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  80. inline DATA_TYPE *getFirstData();
  81. // TRUE if nodes are not in sorted order
  82. inline BOOL corrupt();
  83. protected:
  84. class LLPtrSkipNode
  85. {
  86. public:
  87. LLPtrSkipNode()
  88. : mData(NULL)
  89. {
  90. S32 i;
  91. for (i = 0; i < BINARY_DEPTH; i++)
  92. {
  93. mForward[i] = NULL;
  94. }
  95. }
  96. LLPtrSkipNode(DATA_TYPE *data)
  97. : mData(data)
  98. {
  99. S32 i;
  100. for (i = 0; i < BINARY_DEPTH; i++)
  101. {
  102. mForward[i] = NULL;
  103. }
  104. }
  105. ~LLPtrSkipNode()
  106. {
  107. if (mData)
  108. {
  109. llerror("Attempting to call LLPtrSkipNode destructor with a non-null mDatap!", 1);
  110. }
  111. }
  112. // delete associated data and NULLs out pointer
  113. void deleteData()
  114. {
  115. delete mData;
  116. mData = NULL;
  117. }
  118. // NULLs out pointer
  119. void removeData()
  120. {
  121. mData = NULL;
  122. }
  123. DATA_TYPE *mData;
  124. LLPtrSkipNode *mForward[BINARY_DEPTH];
  125. };
  126. static BOOL defaultEquals(const DATA_TYPE *first, const DATA_TYPE *second)
  127. {
  128. return first == second;
  129. }
  130. LLPtrSkipNode mHead;
  131. LLPtrSkipNode *mUpdate[BINARY_DEPTH];
  132. LLPtrSkipNode *mCurrentp;
  133. LLPtrSkipNode *mCurrentOperatingp;
  134. S32 mLevel;
  135. BOOL (*mInsertFirst)(const DATA_TYPE *first, const DATA_TYPE *second);
  136. BOOL (*mEquals)(const DATA_TYPE *first, const DATA_TYPE *second);
  137. };
  138. // basic constructor
  139. template <class DATA_TYPE, S32 BINARY_DEPTH>
  140. LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList()
  141. : mInsertFirst(NULL), mEquals(defaultEquals)
  142. {
  143. if (BINARY_DEPTH < 2)
  144. {
  145. llerrs << "Trying to create skip list with too little depth, "
  146. "must be 2 or greater" << llendl;
  147. }
  148. S32 i;
  149. for (i = 0; i < BINARY_DEPTH; i++)
  150. {
  151. mUpdate[i] = NULL;
  152. }
  153. mLevel = 1;
  154. mCurrentp = *(mHead.mForward);
  155. mCurrentOperatingp = *(mHead.mForward);
  156. }
  157. // basic constructor including sorter
  158. template <class DATA_TYPE, S32 BINARY_DEPTH>
  159. LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second),
  160. BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second))
  161. :mInsertFirst(insert_first), mEquals(equals)
  162. {
  163. if (BINARY_DEPTH < 2)
  164. {
  165. llerrs << "Trying to create skip list with too little depth, "
  166. "must be 2 or greater" << llendl;
  167. }
  168. mLevel = 1;
  169. S32 i;
  170. for (i = 0; i < BINARY_DEPTH; i++)
  171. {
  172. mHead.mForward[i] = NULL;
  173. mUpdate[i] = NULL;
  174. }
  175. mCurrentp = *(mHead.mForward);
  176. mCurrentOperatingp = *(mHead.mForward);
  177. }
  178. template <class DATA_TYPE, S32 BINARY_DEPTH>
  179. inline LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::~LLPtrSkipList()
  180. {
  181. removeAllNodes();
  182. }
  183. template <class DATA_TYPE, S32 BINARY_DEPTH>
  184. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second))
  185. {
  186. mInsertFirst = insert_first;
  187. }
  188. template <class DATA_TYPE, S32 BINARY_DEPTH>
  189. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second))
  190. {
  191. mEquals = equals;
  192. }
  193. template <class DATA_TYPE, S32 BINARY_DEPTH>
  194. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::addData(DATA_TYPE *data)
  195. {
  196. S32 level;
  197. LLPtrSkipNode *current = &mHead;
  198. LLPtrSkipNode *temp;
  199. // find the pointer one in front of the one we want
  200. if (mInsertFirst)
  201. {
  202. for (level = mLevel - 1; level >= 0; level--)
  203. {
  204. temp = *(current->mForward + level);
  205. while ( (temp)
  206. &&(mInsertFirst(temp->mData, data)))
  207. {
  208. current = temp;
  209. temp = *(current->mForward + level);
  210. }
  211. *(mUpdate + level) = current;
  212. }
  213. }
  214. else
  215. {
  216. for (level = mLevel - 1; level >= 0; level--)
  217. {
  218. temp = *(current->mForward + level);
  219. while ( (temp)
  220. &&(temp->mData < data))
  221. {
  222. current = temp;
  223. temp = *(current->mForward + level);
  224. }
  225. *(mUpdate + level) = current;
  226. }
  227. }
  228. // we're now just in front of where we want to be . . . take one step forward
  229. current = *current->mForward;
  230. // now add the new node
  231. S32 newlevel;
  232. for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
  233. {
  234. if (ll_frand() < 0.5f)
  235. break;
  236. }
  237. LLPtrSkipNode *snode = new LLPtrSkipNode(data);
  238. if (newlevel > mLevel)
  239. {
  240. mHead.mForward[mLevel] = NULL;
  241. mUpdate[mLevel] = &mHead;
  242. mLevel = newlevel;
  243. }
  244. for (level = 0; level < newlevel; level++)
  245. {
  246. snode->mForward[level] = mUpdate[level]->mForward[level];
  247. mUpdate[level]->mForward[level] = snode;
  248. }
  249. return TRUE;
  250. }
  251. template <class DATA_TYPE, S32 BINARY_DEPTH>
  252. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE *data)
  253. {
  254. S32 level;
  255. LLPtrSkipNode *current = &mHead;
  256. LLPtrSkipNode *temp;
  257. // find the pointer one in front of the one we want
  258. if (mInsertFirst)
  259. {
  260. for (level = mLevel - 1; level >= 0; level--)
  261. {
  262. temp = *(current->mForward + level);
  263. while ( (temp)
  264. &&(mInsertFirst(temp->mData, data)))
  265. {
  266. current = temp;
  267. temp = *(current->mForward + level);
  268. }
  269. *(mUpdate + level) = current;
  270. }
  271. }
  272. else
  273. {
  274. for (level = mLevel - 1; level >= 0; level--)
  275. {
  276. temp = *(current->mForward + level);
  277. while ( (temp)
  278. &&(temp->mData < data))
  279. {
  280. current = temp;
  281. temp = *(current->mForward + level);
  282. }
  283. *(mUpdate + level) = current;
  284. }
  285. }
  286. // we're now just in front of where we want to be . . . take one step forward
  287. current = *current->mForward;
  288. if (current)
  289. {
  290. return mEquals(current->mData, data);
  291. }
  292. else
  293. {
  294. return FALSE;
  295. }
  296. }
  297. // returns number of items in the list
  298. template <class DATA_TYPE, S32 BINARY_DEPTH>
  299. inline S32 LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getLength()
  300. {
  301. U32 length = 0;
  302. for (LLPtrSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
  303. {
  304. length++;
  305. }
  306. return length;
  307. }
  308. template <class DATA_TYPE, S32 BINARY_DEPTH>
  309. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE *data)
  310. {
  311. S32 level;
  312. LLPtrSkipNode *current = &mHead;
  313. LLPtrSkipNode *temp;
  314. // find the pointer one in front of the one we want
  315. if (mInsertFirst)
  316. {
  317. for (level = mLevel - 1; level >= 0; level--)
  318. {
  319. temp = *(current->mForward + level);
  320. while ( (temp)
  321. &&(mInsertFirst(temp->mData, data)))
  322. {
  323. current = temp;
  324. temp = *(current->mForward + level);
  325. }
  326. *(mUpdate + level) = current;
  327. }
  328. }
  329. else
  330. {
  331. for (level = mLevel - 1; level >= 0; level--)
  332. {
  333. temp = *(current->mForward + level);
  334. while ( (temp)
  335. &&(temp->mData < data))
  336. {
  337. current = temp;
  338. temp = *(current->mForward + level);
  339. }
  340. *(mUpdate + level) = current;
  341. }
  342. }
  343. // we're now just in front of where we want to be . . . take one step forward
  344. current = *current->mForward;
  345. if (!current)
  346. {
  347. // empty list or beyond the end!
  348. return FALSE;
  349. }
  350. // is this the one we want?
  351. if (!mEquals(current->mData, data))
  352. {
  353. // nope!
  354. return FALSE;
  355. }
  356. else
  357. {
  358. // yes it is! change pointers as required
  359. for (level = 0; level < mLevel; level++)
  360. {
  361. if (mUpdate[level]->mForward[level] != current)
  362. {
  363. // cool, we've fixed all the pointers!
  364. break;
  365. }
  366. mUpdate[level]->mForward[level] = current->mForward[level];
  367. }
  368. // clean up cuurent
  369. current->removeData();
  370. delete current;
  371. // clean up mHead
  372. while ( (mLevel > 1)
  373. &&(!mHead.mForward[mLevel - 1]))
  374. {
  375. mLevel--;
  376. }
  377. }
  378. return TRUE;
  379. }
  380. // note that b_sort is ignored
  381. template <class DATA_TYPE, S32 BINARY_DEPTH>
  382. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort)
  383. {
  384. BOOL removed = removeData(data);
  385. BOOL added = newlist->addData(data);
  386. return removed && added;
  387. }
  388. template <class DATA_TYPE, S32 BINARY_DEPTH>
  389. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort)
  390. {
  391. if (mCurrentOperatingp)
  392. {
  393. mCurrentp = mCurrentOperatingp->mForward[0];
  394. BOOL removed = removeData(mCurrentOperatingp);
  395. BOOL added = newlist->addData(mCurrentOperatingp);
  396. mCurrentOperatingp = mCurrentp;
  397. return removed && added;
  398. }
  399. return FALSE;
  400. }
  401. // resort -- use when the value we're sorting by changes
  402. /* IW 12/6/02 - This doesn't work!
  403. Instead, remove the data BEFORE you change it
  404. Then re-insert it after you change it
  405. BOOL resortData(DATA_TYPE *data)
  406. {
  407. removeData(data);
  408. addData(data);
  409. }
  410. */
  411. // remove all nodes from the list but do not delete data
  412. template <class DATA_TYPE, S32 BINARY_DEPTH>
  413. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
  414. {
  415. LLPtrSkipNode *temp;
  416. // reset mCurrentp
  417. mCurrentp = *(mHead.mForward);
  418. while (mCurrentp)
  419. {
  420. temp = mCurrentp->mForward[0];
  421. mCurrentp->removeData();
  422. delete mCurrentp;
  423. mCurrentp = temp;
  424. }
  425. S32 i;
  426. for (i = 0; i < BINARY_DEPTH; i++)
  427. {
  428. mHead.mForward[i] = NULL;
  429. mUpdate[i] = NULL;
  430. }
  431. mCurrentp = *(mHead.mForward);
  432. mCurrentOperatingp = *(mHead.mForward);
  433. }
  434. template <class DATA_TYPE, S32 BINARY_DEPTH>
  435. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteData(const DATA_TYPE *data)
  436. {
  437. S32 level;
  438. LLPtrSkipNode *current = &mHead;
  439. LLPtrSkipNode *temp;
  440. // find the pointer one in front of the one we want
  441. if (mInsertFirst)
  442. {
  443. for (level = mLevel - 1; level >= 0; level--)
  444. {
  445. temp = *(current->mForward + level);
  446. while ( (temp)
  447. &&(mInsertFirst(temp->mData, data)))
  448. {
  449. current = temp;
  450. temp = *(current->mForward + level);
  451. }
  452. *(mUpdate + level) = current;
  453. }
  454. }
  455. else
  456. {
  457. for (level = mLevel - 1; level >= 0; level--)
  458. {
  459. temp = *(current->mForward + level);
  460. while ( (temp)
  461. &&(temp->mData < data))
  462. {
  463. current = temp;
  464. temp = *(current->mForward + level);
  465. }
  466. *(mUpdate + level) = current;
  467. }
  468. }
  469. // we're now just in front of where we want to be . . . take one step forward
  470. current = *current->mForward;
  471. if (!current)
  472. {
  473. // empty list or beyond the end!
  474. return FALSE;
  475. }
  476. // is this the one we want?
  477. if (!mEquals(current->mData, data))
  478. {
  479. // nope!
  480. return FALSE;
  481. }
  482. else
  483. {
  484. // do we need to fix current or currentop?
  485. if (current == mCurrentp)
  486. {
  487. mCurrentp = current->mForward[0];
  488. }
  489. if (current == mCurrentOperatingp)
  490. {
  491. mCurrentOperatingp = current->mForward[0];
  492. }
  493. // yes it is! change pointers as required
  494. for (level = 0; level < mLevel; level++)
  495. {
  496. if (mUpdate[level]->mForward[level] != current)
  497. {
  498. // cool, we've fixed all the pointers!
  499. break;
  500. }
  501. mUpdate[level]->mForward[level] = current->mForward[level];
  502. }
  503. // clean up cuurent
  504. current->deleteData();
  505. delete current;
  506. // clean up mHead
  507. while ( (mLevel > 1)
  508. &&(!mHead.mForward[mLevel - 1]))
  509. {
  510. mLevel--;
  511. }
  512. }
  513. return TRUE;
  514. }
  515. // remove all nodes from the list and delete data
  516. template <class DATA_TYPE, S32 BINARY_DEPTH>
  517. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteAllData()
  518. {
  519. LLPtrSkipNode *temp;
  520. // reset mCurrentp
  521. mCurrentp = *(mHead.mForward);
  522. while (mCurrentp)
  523. {
  524. temp = mCurrentp->mForward[0];
  525. mCurrentp->deleteData();
  526. delete mCurrentp;
  527. mCurrentp = temp;
  528. }
  529. S32 i;
  530. for (i = 0; i < BINARY_DEPTH; i++)
  531. {
  532. mHead.mForward[i] = NULL;
  533. mUpdate[i] = NULL;
  534. }
  535. mCurrentp = *(mHead.mForward);
  536. mCurrentOperatingp = *(mHead.mForward);
  537. }
  538. // place mCurrentp on first node
  539. template <class DATA_TYPE, S32 BINARY_DEPTH>
  540. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
  541. {
  542. mCurrentp = *(mHead.mForward);
  543. mCurrentOperatingp = *(mHead.mForward);
  544. }
  545. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  546. template <class DATA_TYPE, S32 BINARY_DEPTH>
  547. inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
  548. {
  549. if (mCurrentp)
  550. {
  551. mCurrentOperatingp = mCurrentp;
  552. mCurrentp = *mCurrentp->mForward;
  553. return mCurrentOperatingp->mData;
  554. }
  555. else
  556. {
  557. //return NULL; // causes compile warning
  558. return 0; // equivalent, but no warning
  559. }
  560. }
  561. // same as getCurrentData() but a more intuitive name for the operation
  562. template <class DATA_TYPE, S32 BINARY_DEPTH>
  563. inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
  564. {
  565. if (mCurrentp)
  566. {
  567. mCurrentOperatingp = mCurrentp;
  568. mCurrentp = *mCurrentp->mForward;
  569. return mCurrentOperatingp->mData;
  570. }
  571. else
  572. {
  573. //return NULL; // causes compile warning
  574. return 0; // equivalent, but no warning
  575. }
  576. }
  577. // remove the Node at mCurentOperatingp
  578. // leave mCurrentp and mCurentOperatingp on the next entry
  579. template <class DATA_TYPE, S32 BINARY_DEPTH>
  580. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
  581. {
  582. if (mCurrentOperatingp)
  583. {
  584. removeData(mCurrentOperatingp->mData);
  585. }
  586. }
  587. // delete the Node at mCurentOperatingp
  588. // leave mCurrentp and mCurentOperatingp on the next entry
  589. template <class DATA_TYPE, S32 BINARY_DEPTH>
  590. inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
  591. {
  592. if (mCurrentOperatingp)
  593. {
  594. deleteData(mCurrentOperatingp->mData);
  595. }
  596. }
  597. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  598. template <class DATA_TYPE, S32 BINARY_DEPTH>
  599. inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
  600. {
  601. mCurrentp = *(mHead.mForward);
  602. mCurrentOperatingp = *(mHead.mForward);
  603. if (mCurrentp)
  604. {
  605. mCurrentOperatingp = mCurrentp;
  606. mCurrentp = mCurrentp->mForward[0];
  607. return mCurrentOperatingp->mData;
  608. }
  609. else
  610. {
  611. //return NULL; // causes compile warning
  612. return 0; // equivalent, but no warning
  613. }
  614. }
  615. template <class DATA_TYPE, S32 BINARY_DEPTH>
  616. inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::corrupt()
  617. {
  618. LLPtrSkipNode *previous = mHead.mForward[0];
  619. // Empty lists are not corrupt.
  620. if (!previous) return FALSE;
  621. LLPtrSkipNode *current = previous->mForward[0];
  622. while(current)
  623. {
  624. if (!mInsertFirst(previous->mData, current->mData))
  625. {
  626. // prev shouldn't be in front of cur!
  627. return TRUE;
  628. }
  629. current = current->mForward[0];
  630. }
  631. return FALSE;
  632. }
  633. #endif