PageRenderTime 34ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llskiplist.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 517 lines | 379 code | 65 blank | 73 comment | 44 complexity | 2799fe9dc9bd8cf8040d3d62af05de83 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llskiplist.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_LLSKIPLIST_H
  27. #define LL_LLSKIPLIST_H
  28. #include "llrand.h"
  29. #include "llrand.h"
  30. // NOTA BENE: Insert first needs to be < NOT <=
  31. // Binary depth must be >= 2
  32. template <class DATA_TYPE, S32 BINARY_DEPTH = 10>
  33. class LLSkipList
  34. {
  35. public:
  36. typedef BOOL (*compare)(const DATA_TYPE& first, const DATA_TYPE& second);
  37. typedef compare insert_func;
  38. typedef compare equals_func;
  39. void init();
  40. // basic constructor
  41. LLSkipList();
  42. // basic constructor including sorter
  43. LLSkipList(insert_func insert_first, equals_func equals);
  44. ~LLSkipList();
  45. inline void setInsertFirst(insert_func insert_first);
  46. inline void setEquals(equals_func equals);
  47. inline BOOL addData(const DATA_TYPE& data);
  48. inline BOOL checkData(const DATA_TYPE& data);
  49. // returns number of items in the list
  50. inline S32 getLength() const; // NOT a constant time operation, traverses entire list!
  51. inline BOOL moveData(const DATA_TYPE& data, LLSkipList *newlist);
  52. inline BOOL removeData(const DATA_TYPE& data);
  53. // remove all nodes from the list but do not delete data
  54. inline void removeAllNodes();
  55. // place mCurrentp on first node
  56. inline void resetList();
  57. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  58. inline DATA_TYPE getCurrentData();
  59. // same as getCurrentData() but a more intuitive name for the operation
  60. inline DATA_TYPE getNextData();
  61. // remove the Node at mCurentOperatingp
  62. // leave mCurrentp and mCurentOperatingp on the next entry
  63. inline void removeCurrentData();
  64. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  65. inline DATA_TYPE getFirstData();
  66. class LLSkipNode
  67. {
  68. public:
  69. LLSkipNode()
  70. : mData(0)
  71. {
  72. S32 i;
  73. for (i = 0; i < BINARY_DEPTH; i++)
  74. {
  75. mForward[i] = NULL;
  76. }
  77. }
  78. LLSkipNode(DATA_TYPE data)
  79. : mData(data)
  80. {
  81. S32 i;
  82. for (i = 0; i < BINARY_DEPTH; i++)
  83. {
  84. mForward[i] = NULL;
  85. }
  86. }
  87. ~LLSkipNode()
  88. {
  89. }
  90. DATA_TYPE mData;
  91. LLSkipNode *mForward[BINARY_DEPTH];
  92. private:
  93. // Disallow copying of LLSkipNodes by not implementing these methods.
  94. LLSkipNode(const LLSkipNode &);
  95. LLSkipNode &operator=(const LLSkipNode &);
  96. };
  97. static BOOL defaultEquals(const DATA_TYPE& first, const DATA_TYPE& second)
  98. {
  99. return first == second;
  100. }
  101. private:
  102. LLSkipNode mHead;
  103. LLSkipNode *mUpdate[BINARY_DEPTH];
  104. LLSkipNode *mCurrentp;
  105. LLSkipNode *mCurrentOperatingp;
  106. S32 mLevel;
  107. insert_func mInsertFirst;
  108. equals_func mEquals;
  109. private:
  110. // Disallow copying of LLSkipNodes by not implementing these methods.
  111. LLSkipList(const LLSkipList &);
  112. LLSkipList &operator=(const LLSkipList &);
  113. };
  114. ///////////////////////
  115. //
  116. // Implementation
  117. //
  118. // Binary depth must be >= 2
  119. template <class DATA_TYPE, S32 BINARY_DEPTH>
  120. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::init()
  121. {
  122. S32 i;
  123. for (i = 0; i < BINARY_DEPTH; i++)
  124. {
  125. mHead.mForward[i] = NULL;
  126. mUpdate[i] = NULL;
  127. }
  128. mLevel = 1;
  129. mCurrentp = *(mHead.mForward);
  130. mCurrentOperatingp = *(mHead.mForward);
  131. }
  132. // basic constructor
  133. template <class DATA_TYPE, S32 BINARY_DEPTH>
  134. inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList()
  135. : mInsertFirst(NULL),
  136. mEquals(defaultEquals)
  137. {
  138. init();
  139. }
  140. // basic constructor including sorter
  141. template <class DATA_TYPE, S32 BINARY_DEPTH>
  142. inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList(insert_func insert,
  143. equals_func equals)
  144. : mInsertFirst(insert),
  145. mEquals(equals)
  146. {
  147. init();
  148. }
  149. template <class DATA_TYPE, S32 BINARY_DEPTH>
  150. inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::~LLSkipList()
  151. {
  152. removeAllNodes();
  153. }
  154. template <class DATA_TYPE, S32 BINARY_DEPTH>
  155. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
  156. {
  157. mInsertFirst = insert_first;
  158. }
  159. template <class DATA_TYPE, S32 BINARY_DEPTH>
  160. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(equals_func equals)
  161. {
  162. mEquals = equals;
  163. }
  164. template <class DATA_TYPE, S32 BINARY_DEPTH>
  165. inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::addData(const DATA_TYPE& data)
  166. {
  167. S32 level;
  168. LLSkipNode *current = &mHead;
  169. LLSkipNode *temp;
  170. // find the pointer one in front of the one we want
  171. if (mInsertFirst)
  172. {
  173. for (level = mLevel - 1; level >= 0; level--)
  174. {
  175. temp = *(current->mForward + level);
  176. while ( (temp)
  177. &&(mInsertFirst(temp->mData, data)))
  178. {
  179. current = temp;
  180. temp = *(current->mForward + level);
  181. }
  182. *(mUpdate + level) = current;
  183. }
  184. }
  185. else
  186. {
  187. for (level = mLevel - 1; level >= 0; level--)
  188. {
  189. temp = *(current->mForward + level);
  190. while ( (temp)
  191. &&(temp->mData < data))
  192. {
  193. current = temp;
  194. temp = *(current->mForward + level);
  195. }
  196. *(mUpdate + level) = current;
  197. }
  198. }
  199. // we're now just in front of where we want to be . . . take one step forward
  200. current = *current->mForward;
  201. // now add the new node
  202. S32 newlevel;
  203. for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
  204. {
  205. if (ll_frand() < 0.5f)
  206. break;
  207. }
  208. LLSkipNode *snode = new LLSkipNode(data);
  209. if (newlevel > mLevel)
  210. {
  211. mHead.mForward[mLevel] = NULL;
  212. mUpdate[mLevel] = &mHead;
  213. mLevel = newlevel;
  214. }
  215. for (level = 0; level < newlevel; level++)
  216. {
  217. snode->mForward[level] = mUpdate[level]->mForward[level];
  218. mUpdate[level]->mForward[level] = snode;
  219. }
  220. return TRUE;
  221. }
  222. template <class DATA_TYPE, S32 BINARY_DEPTH>
  223. inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE& data)
  224. {
  225. S32 level;
  226. LLSkipNode *current = &mHead;
  227. LLSkipNode *temp;
  228. // find the pointer one in front of the one we want
  229. if (mInsertFirst)
  230. {
  231. for (level = mLevel - 1; level >= 0; level--)
  232. {
  233. temp = *(current->mForward + level);
  234. while ( (temp)
  235. &&(mInsertFirst(temp->mData, data)))
  236. {
  237. current = temp;
  238. temp = *(current->mForward + level);
  239. }
  240. *(mUpdate + level) = current;
  241. }
  242. }
  243. else
  244. {
  245. for (level = mLevel - 1; level >= 0; level--)
  246. {
  247. temp = *(current->mForward + level);
  248. while ( (temp)
  249. &&(temp->mData < data))
  250. {
  251. current = temp;
  252. temp = *(current->mForward + level);
  253. }
  254. *(mUpdate + level) = current;
  255. }
  256. }
  257. // we're now just in front of where we want to be . . . take one step forward
  258. current = *current->mForward;
  259. if (current)
  260. {
  261. return mEquals(current->mData, data);
  262. }
  263. return FALSE;
  264. }
  265. // returns number of items in the list
  266. template <class DATA_TYPE, S32 BINARY_DEPTH>
  267. inline S32 LLSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() const
  268. {
  269. U32 length = 0;
  270. for (LLSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
  271. {
  272. length++;
  273. }
  274. return length;
  275. }
  276. template <class DATA_TYPE, S32 BINARY_DEPTH>
  277. inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE& data, LLSkipList *newlist)
  278. {
  279. BOOL removed = removeData(data);
  280. BOOL added = newlist->addData(data);
  281. return removed && added;
  282. }
  283. template <class DATA_TYPE, S32 BINARY_DEPTH>
  284. inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE& data)
  285. {
  286. S32 level;
  287. LLSkipNode *current = &mHead;
  288. LLSkipNode *temp;
  289. // find the pointer one in front of the one we want
  290. if (mInsertFirst)
  291. {
  292. for (level = mLevel - 1; level >= 0; level--)
  293. {
  294. temp = *(current->mForward + level);
  295. while ( (temp)
  296. &&(mInsertFirst(temp->mData, data)))
  297. {
  298. current = temp;
  299. temp = *(current->mForward + level);
  300. }
  301. *(mUpdate + level) = current;
  302. }
  303. }
  304. else
  305. {
  306. for (level = mLevel - 1; level >= 0; level--)
  307. {
  308. temp = *(current->mForward + level);
  309. while ( (temp)
  310. &&(temp->mData < data))
  311. {
  312. current = temp;
  313. temp = *(current->mForward + level);
  314. }
  315. *(mUpdate + level) = current;
  316. }
  317. }
  318. // we're now just in front of where we want to be . . . take one step forward
  319. current = *current->mForward;
  320. if (!current)
  321. {
  322. // empty list or beyond the end!
  323. return FALSE;
  324. }
  325. // is this the one we want?
  326. if (!mEquals(current->mData, data))
  327. {
  328. // nope!
  329. return FALSE;
  330. }
  331. else
  332. {
  333. // do we need to fix current or currentop?
  334. if (current == mCurrentp)
  335. {
  336. mCurrentp = current->mForward[0];
  337. }
  338. if (current == mCurrentOperatingp)
  339. {
  340. mCurrentOperatingp = current->mForward[0];
  341. }
  342. // yes it is! change pointers as required
  343. for (level = 0; level < mLevel; level++)
  344. {
  345. if (mUpdate[level]->mForward[level] != current)
  346. {
  347. // cool, we've fixed all the pointers!
  348. break;
  349. }
  350. mUpdate[level]->mForward[level] = current->mForward[level];
  351. }
  352. // clean up cuurent
  353. delete current;
  354. // clean up mHead
  355. while ( (mLevel > 1)
  356. &&(!mHead.mForward[mLevel - 1]))
  357. {
  358. mLevel--;
  359. }
  360. }
  361. return TRUE;
  362. }
  363. // remove all nodes from the list but do not delete data
  364. template <class DATA_TYPE, S32 BINARY_DEPTH>
  365. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
  366. {
  367. LLSkipNode *temp;
  368. // reset mCurrentp
  369. mCurrentp = *(mHead.mForward);
  370. while (mCurrentp)
  371. {
  372. temp = mCurrentp->mForward[0];
  373. delete mCurrentp;
  374. mCurrentp = temp;
  375. }
  376. S32 i;
  377. for (i = 0; i < BINARY_DEPTH; i++)
  378. {
  379. mHead.mForward[i] = NULL;
  380. mUpdate[i] = NULL;
  381. }
  382. mCurrentp = *(mHead.mForward);
  383. mCurrentOperatingp = *(mHead.mForward);
  384. }
  385. // place mCurrentp on first node
  386. template <class DATA_TYPE, S32 BINARY_DEPTH>
  387. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
  388. {
  389. mCurrentp = *(mHead.mForward);
  390. mCurrentOperatingp = *(mHead.mForward);
  391. }
  392. // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  393. template <class DATA_TYPE, S32 BINARY_DEPTH>
  394. inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
  395. {
  396. if (mCurrentp)
  397. {
  398. mCurrentOperatingp = mCurrentp;
  399. mCurrentp = mCurrentp->mForward[0];
  400. return mCurrentOperatingp->mData;
  401. }
  402. else
  403. {
  404. //return NULL; // causes compile warning
  405. return (DATA_TYPE)0; // equivalent, but no warning
  406. }
  407. }
  408. // same as getCurrentData() but a more intuitive name for the operation
  409. template <class DATA_TYPE, S32 BINARY_DEPTH>
  410. inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
  411. {
  412. if (mCurrentp)
  413. {
  414. mCurrentOperatingp = mCurrentp;
  415. mCurrentp = mCurrentp->mForward[0];
  416. return mCurrentOperatingp->mData;
  417. }
  418. else
  419. {
  420. //return NULL; // causes compile warning
  421. return (DATA_TYPE)0; // equivalent, but no warning
  422. }
  423. }
  424. // remove the Node at mCurentOperatingp
  425. // leave mCurrentp and mCurentOperatingp on the next entry
  426. template <class DATA_TYPE, S32 BINARY_DEPTH>
  427. inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
  428. {
  429. if (mCurrentOperatingp)
  430. {
  431. removeData(mCurrentOperatingp->mData);
  432. }
  433. }
  434. // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
  435. template <class DATA_TYPE, S32 BINARY_DEPTH>
  436. inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
  437. {
  438. mCurrentp = *(mHead.mForward);
  439. mCurrentOperatingp = *(mHead.mForward);
  440. if (mCurrentp)
  441. {
  442. mCurrentOperatingp = mCurrentp;
  443. mCurrentp = mCurrentp->mForward[0];
  444. return mCurrentOperatingp->mData;
  445. }
  446. else
  447. {
  448. //return NULL; // causes compile warning
  449. return (DATA_TYPE)0; // equivalent, but no warning
  450. }
  451. }
  452. #endif