1 #ifndef __SKIPLIST_H__
2 #define __SKIPLIST_H__
3
4 // This file (C) 2004-2009 Steven Boswell. All rights reserved.
5 // Released to the public under the GNU General Public License v2.
6 // See the file COPYING for more information.
7
8 /* A skip list is a sorted data structure with probabilistic balancing
9 that performs the same functions as balanced-binary-tree sorts of
10 data structures, but skip lists have lots of unusual avenues for
11 optimizations not available to binary trees. */
12
13 #include "config.h"
14 #include <assert.h>
15 #include <stdlib.h>
16 #include <new>
17 #include "mjpeg_types.h"
18 #include "Status_t.h"
19 #include "Allocator.hh"
20
21
22
23 // Define this to compile in code to double-check and debug the skip
24 // list.
25 #ifndef NDEBUG
26 // #define DEBUG_SKIPLIST
27 #endif // NDEBUG
28
29
30
31 // The skip list. Parameterized by the class of the sorting key, the
32 // class of the contained value, the method for extracting the key from
33 // the value, the method for comparing keys, the number of forward pointers
34 // in the header, and the type of allocator to use for skip-list nodes.
35 template <class KEY, class VALUE, class KEYFN, class PRED,
36 int HC = 10, class ALLOC = Allocator<HC> >
37 class SkipList
38 {
39 private:
40 // The type of a node in the skip list.
41 struct Node
42 {
43 VALUE m_oValue;
44 // The data held by this node.
45 #ifdef DEBUG_SKIPLIST
46 int32_t m_nLevel;
47 #endif // DEBUG_SKIPLIST
48 // The number of forward pointers in this node.
49 Node *m_pBackward;
50 // The node before this one.
51 Node *m_apForward[1];
52 // The nodes after this one, at all the levels we exist.
53 };
54
55 SkipList (const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther);
56 const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &operator =
57 (const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther);
58 // Disallow copying and assignment.
59
60 enum { HEADERCHUNK = HC };
61 // The number of forward pointers in the header.
62 // Will give good sorting for up to e^HC items.
63
64 public:
65 typedef ALLOC Allocator_t;
66 // The type of node allocator to use.
67
68 static Allocator_t sm_oNodeAllocator;
69 // The default node allocator.
70
71 // A structure that contains all of our initialization parameters.
72 struct InitParams
73 {
74 public:
75 uint32_t m_nRandSeed;
76 // The skip list's random number seed.
77
78 bool m_bAllocateInternalNodesFromAllocator;
79 // True if the skip list's internal nodes (i.e. the header
80 // and search-fingers) should be allocated from the allocator.
81 // False if they should be allocated from system memory.
82 //
83 // Since these nodes live for the lifetime of the skip-list,
84 // allocating them from the allocator prevents the allocator
85 // from being able to purge itself.
86
InitParamsSkipList::InitParams87 InitParams() : m_nRandSeed (rand()),
88 m_bAllocateInternalNodesFromAllocator (false) {}
89 // Default constructor.
90 // Gets the random seed from the system.
91
InitParamsSkipList::InitParams92 InitParams (uint32_t a_nRandSeed,
93 bool a_bAllocateInternalNodesFromAllocator)
94 : m_nRandSeed (a_nRandSeed),
95 m_bAllocateInternalNodesFromAllocator
96 (a_bAllocateInternalNodesFromAllocator) {}
97 // Initializing constructor.
98 };
99
100 SkipList (const PRED &a_rPred = PRED(),
101 Allocator_t &a_rAlloc = sm_oNodeAllocator);
102 // Default constructor. Must be followed by Init().
103
104 SkipList (Status_t &a_reStatus, bool a_bAllowDuplicates,
105 const InitParams &a_rInitParams, const PRED &a_rPred = PRED(),
106 Allocator_t &a_rAlloc = sm_oNodeAllocator);
107 // Constructor. Specify whether or not duplicates are allowed,
108 // and provide a random number seed.
109
110 void Init (Status_t &a_reStatus, bool a_bAllowDuplicates,
111 const InitParams &a_rInitParams);
112 // Construction method. Specify whether or not duplicates are
113 // allowed, and provide a random number seed.
114
115 virtual ~SkipList (void);
116 // Destructor.
117
118 #ifdef DEBUG_SKIPLIST
119
120 void Invariant (void) const;
121 // Thoroughly analyze the skip list for structural integrity.
122
123 void SetDebug (bool a_bDebug);
124 // Set whether to run the skip-list invariant before and after
125 // methods.
126
127 #endif // DEBUG_SKIPLIST
128
129 //
130 // Iterator classes.
131 //
132
133 class Iterator;
134 class ConstIterator;
135 friend class ConstIterator;
136 class ConstIterator
137 {
138 protected:
139 friend class SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>;
140 // Let SkipList access m_pNode.
141 Node *m_pNode;
142 // The node we represent.
143 public:
ConstIterator()144 ConstIterator() { m_pNode = NULL; }
ConstIterator(Node * a_pNode)145 ConstIterator (Node *a_pNode) : m_pNode (a_pNode) {}
ConstIterator(const Iterator & a_rOther)146 ConstIterator (const Iterator &a_rOther)
147 : m_pNode (a_rOther.m_pNode) {}
operator *() const148 const VALUE &operator*() const {return m_pNode->m_oValue; }
operator ++()149 ConstIterator& operator++()
150 { m_pNode = m_pNode->m_apForward[0];
151 return *this; }
operator ++(int)152 ConstIterator operator++(int) { ConstIterator oTmp = *this;
153 ++*this; return oTmp; }
operator --()154 ConstIterator& operator--()
155 { m_pNode = m_pNode->m_pBackward;
156 return *this; }
operator --(int)157 ConstIterator operator--(int) { ConstIterator oTmp = *this;
158 --*this; return oTmp; }
operator ==(const ConstIterator & a_rOther) const159 bool operator== (const ConstIterator &a_rOther) const
160 { return (m_pNode == a_rOther.m_pNode) ? true : false; }
operator !=(const ConstIterator & a_rOther) const161 bool operator!= (const ConstIterator &a_rOther) const
162 { return (m_pNode != a_rOther.m_pNode) ? true : false; }
163 };
164 friend class Iterator;
165 class Iterator : public ConstIterator
166 {
167 private:
168 typedef ConstIterator BaseClass;
169 // Keep track of who our base class is.
170
171 public:
Iterator()172 Iterator() : ConstIterator() {}
Iterator(Node * a_pNode)173 Iterator (Node *a_pNode) : ConstIterator (a_pNode) {}
operator *()174 VALUE &operator*() {return BaseClass::m_pNode->m_oValue; }
operator ++()175 Iterator& operator++() { BaseClass::m_pNode
176 = BaseClass::m_pNode->m_apForward[0]; return *this; }
operator ++(int)177 Iterator operator++(int) { Iterator oTmp = *this; ++*this;
178 return oTmp; }
operator --()179 Iterator& operator--() { BaseClass::m_pNode
180 = BaseClass::m_pNode->m_pBackward; return *this; }
operator --(int)181 Iterator operator--(int) { Iterator oTmp = *this; --*this;
182 return oTmp; }
operator ==(const ConstIterator & a_rOther) const183 bool operator== (const ConstIterator &a_rOther) const
184 { return (((BaseClass&)(*this)) == a_rOther); }
operator !=(const ConstIterator & a_rOther) const185 bool operator!= (const ConstIterator &a_rOther) const
186 { return (((BaseClass&)(*this)) != a_rOther); }
187 };
188
189 //
190 // Skip list methods.
191 //
192
Begin(void)193 Iterator Begin (void)
194 { return Iterator (m_pHeader->m_apForward[0]); }
195 // Return an iterator to the beginning of the list.
196
Begin(void) const197 ConstIterator Begin (void) const
198 { return ConstIterator (m_pHeader->m_apForward[0]); }
199 // Return an iterator to the beginning of the list.
200
End(void)201 Iterator End (void) { return Iterator (m_pHeader); }
202 // Return an iterator to the end of the list.
203
End(void) const204 ConstIterator End (void) const { return ConstIterator (m_pHeader); }
205 // Return an iterator to the end of the list.
206
Size(void) const207 uint32_t Size (void) const { return m_nItems; }
208 // Return the number of items in the list.
209 // (May be called on a default-constructed object, making it
210 // possible for default-constructed subclasses/owners to destroy
211 // themselves safely.)
212
Empty(void) const213 bool Empty (void) const { return (m_nItems == 0) ? true : false; }
214 // Return whether the list is empty.
215
216 // A structure used to return the result of an insertion.
217 struct InsertResult
218 {
219 Iterator m_itPosition;
220 // Where the item was inserted, or where the duplicate was
221 // found.
222
223 bool m_bInserted;
224 // true if the item was inserted into the list.
225 };
226
227 InsertResult Insert (Status_t &a_reStatus, const VALUE &a_rValue);
228 // Insert an item into the list.
229
230 Iterator Insert (Status_t &a_reStatus, Iterator a_oPosition,
231 const VALUE &a_rValue);
232 // Insert an item into the list, at this exact location, if it's
233 // safe. Returns where it was really inserted.
234
235 void Insert (Status_t &a_reStatus, ConstIterator a_oFirst,
236 ConstIterator a_oLast);
237 // Insert a range of items from another skip-list.
238
239 Iterator Erase (Iterator a_oHere);
240 // Erase the item here. Return the item following the one
241 // removed.
242
243 Iterator Erase (Iterator a_oFirst, Iterator a_oLast);
244 // Erase a range of items in this list. Return the item
245 // following the last one removed.
246
247 void Clear (void);
248 // Empty the list.
249
Purge(void)250 void Purge (void) { }
251 // Purge all internally-allocated memory.
252 // Not implemented for SkipList -- this is only here to preserve
253 // interface compatibility with Vector<>.
254
255 InsertResult Move (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther,
256 Iterator a_oHere);
257 // Remove an item from another skip list and insert it into
258 // ourselves.
259 // Just like an Erase() followed by an Insert(), except that
260 // there's no possibility of the operation failing.
261
262 void Move (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther,
263 Iterator a_oFirst, Iterator a_oLast);
264 // Remove a range of items from another skip-list and insert
265 // them into ourselves.
266 // Just like an Erase() followed by an Insert(), except that
267 // there's no possibility of the operation failing.
268
269 void Move (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther);
270 // Move all items from the other skip-list to ourself.
271 // The current skip-list must be empty.
272
273 bool CanMove (const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther)
274 const;
275 // Returns true if the two skip lists can move items between
276 // each other.
277
278 void Assign (Status_t &a_reStatus,
279 const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther);
280 // Assign the contents of the other skip list to ourselves.
281
282 Iterator Find (const KEY &a_rKey);
283 // Find the given item in the list. Returns End() if not found.
284
285 ConstIterator Find (const KEY &a_rKey) const;
286 // Find the given item in the list. Returns End() if not found.
287
288 Iterator LowerBound (const KEY &a_rKey);
289 // Return the position of the first item that's >= the key.
290
291 ConstIterator LowerBound (const KEY &a_rKey) const;
292 // Return the position of the first item that's >= the key.
293
294 Iterator UpperBound (const KEY &a_rKey);
295 // Return the position of the first item that's > the key.
296
297 ConstIterator UpperBound (const KEY &a_rKey) const;
298 // Return the position of the first item that's > the key.
299
300 size_t GetSizeOfLargestNode (void) const;
301 // Return the size of the largest possible skip-list node.
302 //
303 // (Not generally useful...needed by VariableSizeAllocator,
304 // to make sure all free-space blocks can become part of an
305 // in-place skip-list.)
306
307 private:
308
309 Allocator_t &m_rNodeAllocator;
310 // Where we get memory to allocate nodes.
311
312 bool m_bAllowDuplicates;
313 // true if we allow duplicate elements.
314
315 int16_t m_nHeaderLevel;
316 // How many valid pointers m_pHeader[] is holding.
317
318 Node *m_pHeader;
319 // The beginning of the list.
320
321 Node *m_pSearchFinger, *m_pSearchFinger2;
322 // Used to speed up searches, by caching the results of
323 // previous searches.
324
325 uint32_t m_nItems;
326 // The number of items in this list.
327
328 uint32_t m_nRandSeed;
329 // The random-number seed.
330
331 bool m_bAllocateInternalNodesFromAllocator;
332 // True if the skip list's internal nodes (i.e. the header
333 // and search-fingers) should be allocated from the allocator.
334 // False if they should be allocated from system memory.
335 //
336 // Since these nodes live for the lifetime of the skip-list,
337 // allocating them from the allocator prevents the allocator
338 // from being able to purge itself.
339
340 KEYFN m_oKeyFn;
341 // How we extract a key from a value.
342
343 PRED m_oPred;
344 // How we compare keys to each other.
345
346 void SearchLower (const KEY &a_rKey, Node *a_pTraverse) const;
347 // Search for an item greater than or equal to a_rKey.
348
349 bool SearchExact (Node *a_pKey, Node *a_pTraverse) const;
350 // Search for this exact item. Returns true if it's found.
351
352 void SearchUpper (const KEY &a_rKey, Node *a_pTraverse) const;
353 // Search for an item greater than a_rKey.
354
355 void SearchEnd (Node *a_pTraverse) const;
356 // Point to the end of the list.
357
358 void InsertNode (Node *a_pNewNode, int16_t a_nNewLevel,
359 Node *a_pTraverse);
360 // Insert a new node into the skip list. Assume a_pTraverse is
361 // set up.
362
363 Node *RemoveNode (Node *a_pToRemove, Node *a_pTraverse,
364 int16_t *a_pLevel = NULL);
365 // Remove the given node from the skip list. Assume a_pTraverse
366 // is set up.
367 // Returns the node that got removed, and optionally backpatches
368 // its level.
369
370 Node *GetNewNode (int16_t a_nForwardPointers);
371 // Allocate a new node with the given number of forward
372 // pointers. Returns NULL if something goes wrong.
373
374 Node *GetNewNodeOfRandomLevel (int16_t &a_rnLevel);
375 // Allocate a new node with a random number of forward pointers.
376 // Returns NULL if something goes wrong; otherwise, a_rnLevel
377 // gets backpatched with the number of levels.
378
379 void DeleteNode (int16_t a_nForwardPointers, Node *a_pToDelete);
380 // Delete a node.
381
382 void DeallocateNode (int16_t a_nForwardPointers, Node *a_pToDelete);
383 // Deallocate a node's storage.
384
385 int16_t Rand (void);
386 // Get another random number.
387
388 #ifdef DEBUG_SKIPLIST
389 bool m_bDebug;
390 #endif // DEBUG_SKIPLIST
391 // true if the invariant should be checked.
392 };
393
394
395
396 // The default node allocator. Allocates 64K at a time.
397 template <class KEY, class VALUE, class KEYFN, class PRED,
398 int HC, class ALLOC>
399 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Allocator_t
400 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::sm_oNodeAllocator (65536);
401
402
403
404 // Default constructor. Must be followed by Init().
405 template <class KEY, class VALUE, class KEYFN, class PRED,
406 int HC, class ALLOC>
SkipList(const PRED & a_rPred,Allocator_t & a_rAlloc)407 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SkipList (const PRED &a_rPred,
408 Allocator_t &a_rAlloc)
409 : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred)
410 {
411 // Set up some defaults.
412 m_bAllowDuplicates = false;
413 m_nHeaderLevel = 0;
414 m_pHeader = NULL;
415 m_pSearchFinger = NULL;
416 m_pSearchFinger2 = NULL;
417 m_nItems = 0;
418 m_nRandSeed = 0;
419 m_bAllocateInternalNodesFromAllocator = false;
420 #ifdef DEBUG_SKIPLIST
421 m_bDebug = false;
422
423 // Make sure we're intact.
424 Invariant();
425 #endif // DEBUG_SKIPLIST
426 }
427
428
429
430 // Constructor. Specify whether or not duplicates are allowed, and
431 // provide a random number seed.
432 template <class KEY, class VALUE, class KEYFN, class PRED,
433 int HC, class ALLOC>
SkipList(Status_t & a_reStatus,bool a_bAllowDuplicates,const InitParams & a_rInitParams,const PRED & a_rPred,Allocator_t & a_rAlloc)434 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SkipList (Status_t &a_reStatus,
435 bool a_bAllowDuplicates, const InitParams &a_rInitParams,
436 const PRED &a_rPred, Allocator_t &a_rAlloc)
437 : m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred)
438 {
439 // Make sure they didn't start us off with an error.
440 assert (a_reStatus == g_kNoError);
441
442 // Set up some defaults.
443 m_bAllowDuplicates = false;
444 m_nHeaderLevel = 0;
445 m_pHeader = NULL;
446 m_pSearchFinger = NULL;
447 m_pSearchFinger2 = NULL;
448 m_nItems = 0;
449 m_nRandSeed = 0;
450 m_bAllocateInternalNodesFromAllocator = false;
451 #ifdef DEBUG_SKIPLIST
452 m_bDebug = false;
453 #endif // DEBUG_SKIPLIST
454
455 // Init() does all the work.
456 Init (a_reStatus, a_bAllowDuplicates, a_rInitParams);
457 }
458
459
460
461 // Construction method. Specify whether or not duplicates are allowed,
462 // and provide a random number seed.
463 template <class KEY, class VALUE, class KEYFN, class PRED,
464 int HC, class ALLOC>
465 void
Init(Status_t & a_reStatus,bool a_bAllowDuplicates,const InitParams & a_rInitParams)466 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Init (Status_t &a_reStatus,
467 bool a_bAllowDuplicates, const InitParams &a_rInitParams)
468 {
469 // Make sure they didn't start us off with an error.
470 assert (a_reStatus == g_kNoError);
471
472 // Make sure we haven't been initialized already.
473 assert (m_pHeader == NULL);
474
475 // Fill in the blanks.
476 m_bAllowDuplicates = a_bAllowDuplicates;
477 m_nHeaderLevel = 0;
478 m_nItems = 0;
479 m_nRandSeed = a_rInitParams.m_nRandSeed;
480 m_bAllocateInternalNodesFromAllocator
481 = a_rInitParams.m_bAllocateInternalNodesFromAllocator;
482
483 // Allocate our necessary nodes.
484 if (m_bAllocateInternalNodesFromAllocator)
485 {
486 m_pHeader = GetNewNode (HEADERCHUNK);
487 m_pSearchFinger = GetNewNode (HEADERCHUNK);
488 m_pSearchFinger2 = GetNewNode (HEADERCHUNK);
489 }
490 else
491 {
492 // Do this from system memory, instead of the supplied allocator.
493 // Otherwise, these "permanent" allocations won't allow the
494 // allocator to purge itself during the lifetime of this skip-list.
495 size_t nHeaderBytes = (size_t)(&(((Node *)0x80000000)
496 ->m_apForward[HEADERCHUNK])) - 0x80000000;
497 m_pHeader = (Node *) malloc (nHeaderBytes);
498 m_pSearchFinger = (Node *) malloc (nHeaderBytes);
499 m_pSearchFinger2 = (Node *) malloc (nHeaderBytes);
500 }
501 if (m_pHeader == NULL || m_pSearchFinger == NULL
502 || m_pSearchFinger2 == NULL)
503 {
504 if (m_bAllocateInternalNodesFromAllocator)
505 {
506 if (m_pSearchFinger2 != NULL)
507 DeallocateNode (HEADERCHUNK, m_pSearchFinger2);
508 if (m_pSearchFinger != NULL)
509 DeallocateNode (HEADERCHUNK, m_pSearchFinger);
510 if (m_pHeader != NULL)
511 DeallocateNode (HEADERCHUNK, m_pHeader);
512 }
513 else
514 {
515 free (m_pSearchFinger2);
516 free (m_pSearchFinger);
517 free (m_pHeader);
518 }
519 m_pHeader = NULL;
520 m_pSearchFinger = NULL;
521 m_pSearchFinger2 = NULL;
522 a_reStatus = g_kOutOfMemory;
523 return;
524 }
525
526 // Set up our nodes.
527 //
528 // The way we work, incrementing End() gets you Begin(), and
529 // decrementing Begin() gets you End(). We implement that by using
530 // our header node as a NULL-like sentinel node.
531 #ifdef DEBUG_SKIPLIST
532 m_pHeader->m_nLevel = HEADERCHUNK;
533 m_pSearchFinger->m_nLevel = HEADERCHUNK;
534 m_pSearchFinger2->m_nLevel = HEADERCHUNK;
535 #endif // DEBUG_SKIPLIST
536 new ((void *)(&(m_pHeader->m_oValue))) VALUE;
537 new ((void *)(&(m_pSearchFinger->m_oValue))) VALUE;
538 new ((void *)(&(m_pSearchFinger2->m_oValue))) VALUE;
539 m_pHeader->m_pBackward = m_pHeader;
540 m_pSearchFinger->m_pBackward = m_pHeader;
541 m_pSearchFinger2->m_pBackward = m_pHeader;
542 for (int16_t nI = 0; nI < HEADERCHUNK; nI++)
543 {
544 m_pHeader->m_apForward[nI] = m_pHeader;
545 m_pSearchFinger->m_apForward[nI] = m_pHeader;
546 m_pSearchFinger2->m_apForward[nI] = m_pHeader;
547 }
548
549 // Make sure we're intact.
550 #ifdef DEBUG_SKIPLIST
551 Invariant();
552 #endif // DEBUG_SKIPLIST
553 }
554
555
556
557 // Destructor.
558 template <class KEY, class VALUE, class KEYFN, class PRED,
559 int HC, class ALLOC>
~SkipList(void)560 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::~SkipList (void)
561 {
562 // Make sure we're intact.
563 #ifdef DEBUG_SKIPLIST
564 Invariant();
565 #endif // DEBUG_SKIPLIST
566
567 // If we have anything to delete, delete it.
568 if (m_pHeader != NULL)
569 {
570 // Delete everything in the list.
571 Erase (Begin(), End());
572
573 // Free up our extra nodes.
574 m_pSearchFinger2->m_oValue.~VALUE();
575 m_pSearchFinger->m_oValue.~VALUE();
576 m_pHeader->m_oValue.~VALUE();
577 if (m_bAllocateInternalNodesFromAllocator)
578 {
579 DeallocateNode (HEADERCHUNK, m_pSearchFinger2);
580 DeallocateNode (HEADERCHUNK, m_pSearchFinger);
581 DeallocateNode (HEADERCHUNK, m_pHeader);
582 }
583 else
584 {
585 free (m_pSearchFinger2);
586 free (m_pSearchFinger);
587 free (m_pHeader);
588 }
589 }
590 }
591
592
593
594 #ifdef DEBUG_SKIPLIST
595
596 // Set whether to run the skip-list invariant before and after methods.
597 template <class KEY, class VALUE, class KEYFN, class PRED,
598 int HC, class ALLOC>
599 void
SetDebug(bool a_bDebug)600 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SetDebug (bool a_bDebug)
601 {
602 // Easy enough.
603 m_bDebug = a_bDebug;
604 }
605
606 #endif // DEBUG_SKIPLIST
607
608
609
610 // Insert an item into the list.
611 template <class KEY, class VALUE, class KEYFN, class PRED,
612 int HC, class ALLOC>
613 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::InsertResult
Insert(Status_t & a_reStatus,const VALUE & a_rValue)614 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Insert (Status_t &a_reStatus,
615 const VALUE &a_rValue)
616 {
617 Node *pNewNode;
618 // The new node being inserted.
619 int16_t nNewLevel;
620 // The level of the new node.
621 InsertResult oInsertResult;
622 // The result of the insertion.
623
624 // Make sure we're intact.
625 #ifdef DEBUG_SKIPLIST
626 Invariant();
627 #endif // DEBUG_SKIPLIST
628
629 // Make sure they didn't start us off with an error.
630 assert (a_reStatus == g_kNoError);
631
632 // Make sure we have been initialized properly.
633 assert (m_pHeader != NULL);
634
635 // Find where to put this key. (Put equal keys at the upper bound.)
636 SearchUpper (m_oKeyFn (a_rValue), m_pSearchFinger);
637
638 // Insert this node if there's no duplicate already in here.
639 if (m_bAllowDuplicates
640 || (pNewNode = m_pSearchFinger->m_apForward[0],
641 pNewNode == m_pHeader
642 || m_oPred (m_oKeyFn (pNewNode->m_oValue),
643 m_oKeyFn (a_rValue))))
644 {
645 // Generate a node of random level.
646 pNewNode = GetNewNodeOfRandomLevel (nNewLevel);
647 if (pNewNode == NULL)
648 {
649 // We couldn't allocate space.
650 a_reStatus = g_kOutOfMemory;
651 oInsertResult.m_itPosition = End();
652 oInsertResult.m_bInserted = false;
653 return oInsertResult;
654 }
655
656 // Install the value.
657 new ((void *)(&(pNewNode->m_oValue))) VALUE (a_rValue);
658
659 // Put it into the skip list here.
660 InsertNode (pNewNode, nNewLevel, m_pSearchFinger);
661
662 // Let them know where we put it, and that we did insert it.
663 oInsertResult.m_itPosition = Iterator (pNewNode);
664 oInsertResult.m_bInserted = true;
665 }
666 else
667 {
668 // We didn't insert it. Show them the equal item.
669 oInsertResult.m_itPosition = Iterator (pNewNode);
670 oInsertResult.m_bInserted = false;
671 }
672
673 // Make sure we're intact.
674 #ifdef DEBUG_SKIPLIST
675 Invariant();
676 #endif // DEBUG_SKIPLIST
677
678 // Let them know what happened.
679 return oInsertResult;
680 }
681
682
683
684 // Insert an item into the list, at this exact location, if it's safe.
685 // Returns where it was really inserted.
686 template <class KEY, class VALUE, class KEYFN, class PRED,
687 int HC, class ALLOC>
688 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
Insert(Status_t & a_reStatus,Iterator a_oPosition,const VALUE & a_rValue)689 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Insert (Status_t &a_reStatus,
690 Iterator a_oPosition, const VALUE &a_rValue)
691 {
692 const KEY &rKey = m_oKeyFn (a_rValue);
693 // The key of what they're inserting.
694 Node *pNewNode;
695 // The node we're inserting.
696 int16_t nNewLevel;
697 // The level it's at.
698 Iterator oHere;
699 // Where it gets inserted.
700
701 // Make sure we're intact.
702 #ifdef DEBUG_SKIPLIST
703 Invariant();
704 #endif // DEBUG_SKIPLIST
705
706 // Make sure they didn't start us off with an error.
707 assert (a_reStatus == g_kNoError);
708
709 // Make sure we have been initialized properly.
710 assert (m_pHeader != NULL);
711
712 // According to STL semantics, the insertion point must immediately
713 // follow a_oPosition. To fit more naturally with skip-list
714 // semantics, the insertion point needs to precede a_oPosition.
715 if (a_oPosition != End())
716 ++a_oPosition;
717
718 // The new item has to fit where this iterator points, and we must
719 // be able to find this iterator's node in the list.
720 Iterator oBefore = a_oPosition; --oBefore;
721 if ((a_oPosition.m_pNode != m_pHeader
722 && m_oPred (m_oKeyFn (a_oPosition.m_pNode->m_oValue), rKey))
723 || (oBefore.m_pNode != m_pHeader
724 && m_oPred (rKey, m_oKeyFn (oBefore.m_pNode->m_oValue)))
725 || !SearchExact (a_oPosition.m_pNode, m_pSearchFinger))
726 {
727 // Don't use their iterator.
728 oHere = Insert (a_reStatus, a_rValue).m_itPosition;
729 }
730
731 // Insert this node if we always insert, or if there's no duplicate
732 // already.
733 else if (m_bAllowDuplicates
734 || (pNewNode = m_pSearchFinger->m_apForward[0]->m_apForward[0],
735 pNewNode == m_pHeader
736 || m_oPred (rKey, m_oKeyFn (pNewNode->m_oValue))))
737 {
738 // Generate a node of random level.
739 pNewNode = GetNewNodeOfRandomLevel (nNewLevel);
740 if (pNewNode == NULL)
741 {
742 // We couldn't allocate space.
743 a_reStatus = g_kOutOfMemory;
744 oHere = End();
745 }
746 else
747 {
748 // Install the value.
749 new ((void *)(&(pNewNode->m_oValue))) VALUE (a_rValue);
750
751 // Put it into the skip list here.
752 InsertNode (pNewNode, nNewLevel, m_pSearchFinger);
753
754 // Let them know where we put it.
755 oHere = Iterator (pNewNode);
756 }
757 }
758
759 // We didn't insert it. Show them the equal item.
760 else
761 oHere = Iterator (pNewNode);
762
763 // Make sure we're intact.
764 #ifdef DEBUG_SKIPLIST
765 Invariant();
766 #endif // DEBUG_SKIPLIST
767
768 // Let our caller know what happened.
769 return oHere;
770 }
771
772
773
774 // Insert a range of items from another skip-list.
775 template <class KEY, class VALUE, class KEYFN, class PRED,
776 int HC, class ALLOC>
777 void
Insert(Status_t & a_reStatus,ConstIterator a_oFirst,ConstIterator a_oLast)778 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Insert (Status_t &a_reStatus,
779 ConstIterator a_oFirst, ConstIterator a_oLast)
780 {
781 ConstIterator oHere;
782 // The next item to insert.
783
784 // Make sure they didn't start us off with an error.
785 assert (a_reStatus == g_kNoError);
786
787 // Make sure we have been initialized properly.
788 assert (m_pHeader != NULL);
789
790 // Try to insert every item they gave us.
791 for (oHere = a_oFirst; oHere != a_oLast; oHere++)
792 {
793 Insert (a_reStatus, *oHere);
794 if (a_reStatus != g_kNoError)
795 {
796 // BUG: this is messy. If we can't insert the entire range,
797 // we shouldn't insert any of it. Fix this by preallocating
798 // all necessary nodes.
799 return;
800 }
801 }
802 }
803
804
805
806 // Erase the item here. Return the item following the one removed.
807 template <class KEY, class VALUE, class KEYFN, class PRED,
808 int HC, class ALLOC>
809 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
Erase(Iterator a_oHere)810 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Erase (Iterator a_oHere)
811 {
812 Node *pToRemove;
813 int16_t nLevel;
814 // The node being deleted, and its level.
815
816 // Make sure we have been initialized properly.
817 assert (m_pHeader != NULL);
818
819 // Make sure we're intact.
820 #ifdef DEBUG_SKIPLIST
821 Invariant();
822 #endif // DEBUG_SKIPLIST
823
824 // Don't let them erase End().
825 if (a_oHere.m_pNode == m_pHeader)
826 return Begin();
827
828 // If this iterator does not point to a current node, leave.
829 // (This check also sets up the search finger for RemoveNode().)
830 if (!SearchExact (a_oHere.m_pNode, m_pSearchFinger))
831 return Begin();
832
833 // Erase it.
834 pToRemove = RemoveNode (m_pSearchFinger->m_apForward[0]
835 ->m_apForward[0], m_pSearchFinger, &nLevel);
836 DeleteNode (nLevel, pToRemove);
837
838 // Make sure we're intact.
839 #ifdef DEBUG_SKIPLIST
840 Invariant();
841 #endif // DEBUG_SKIPLIST
842
843 // Return an iterator that points past the deleted node.
844 return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]);
845 }
846
847
848
849 // Erase a range of items in this list. Return the item following the
850 // last one removed.
851 template <class KEY, class VALUE, class KEYFN, class PRED,
852 int HC, class ALLOC>
853 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
Erase(Iterator a_oFirst,Iterator a_oLast)854 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Erase (Iterator a_oFirst,
855 Iterator a_oLast)
856 {
857 int16_t nI;
858 // Used to loop through things.
859 Node *pNode, *pToRemove;
860 // Nodes we're examining and deleting.
861 int16_t nLevel;
862 // The level of each removed node.
863
864 // Make sure we're intact.
865 #ifdef DEBUG_SKIPLIST
866 Invariant();
867 #endif // DEBUG_SKIPLIST
868
869 // Make sure we have been initialized properly.
870 assert (m_pHeader != NULL);
871
872 // Make sure these iterators are in the right order.
873 assert (a_oFirst == Begin()
874 || a_oLast == End()
875 || !m_oPred (m_oKeyFn (a_oLast.m_pNode->m_oValue),
876 m_oKeyFn (a_oFirst.m_pNode->m_oValue)));
877
878 // If the first item to be removed is the end of the list, then
879 // nothing needs to be done.
880 if (a_oFirst == End())
881 return End();
882
883 // A skip-list's range-delete doesn't involve a rebalancing for
884 // every node deleted, like a tree structure's range-delete would.
885 // Here, we just generate search fingers for each end of the
886 // range, and fix the forward/backward pointers in one shot.
887 // We still have to loop through the deleted range in order to
888 // delete the nodes, but that's nowhere near the cost of a
889 // rebalance per node. Spiffy, huh?
890
891 // First, search for the beginning of the range to delete.
892 // Abort if we can't find it.
893 if (!SearchExact (a_oFirst.m_pNode, m_pSearchFinger))
894 return End();
895
896 // Use that as a base for the second search.
897 for (nI = 0; nI < m_nHeaderLevel; nI++)
898 m_pSearchFinger2->m_apForward[nI]
899 = m_pSearchFinger->m_apForward[nI];
900
901 // Now search for the end of the range to delete.
902 // Abort if we can't find it.
903 if (!SearchExact (a_oLast.m_pNode, m_pSearchFinger2))
904 return End();
905
906 // Loop through the removed nodes, destroy the values inside,
907 // and deallocate the nodes.
908 pNode = a_oFirst.m_pNode;
909 while (pNode != a_oLast.m_pNode)
910 {
911 // Get the node to destroy.
912 pToRemove = pNode;
913 pNode = pNode->m_apForward[0];
914
915 // Destroy it.
916 pToRemove = RemoveNode (pToRemove, m_pSearchFinger, &nLevel);
917 DeleteNode (nLevel, pToRemove);
918 }
919
920 // Make sure we're intact.
921 #ifdef DEBUG_SKIPLIST
922 Invariant();
923 #endif // DEBUG_SKIPLIST
924
925 // Return the end of the removed range.
926 return a_oLast;
927 }
928
929
930
931 // Empty the list.
932 template <class KEY, class VALUE, class KEYFN, class PRED,
933 int HC, class ALLOC>
934 void
Clear(void)935 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Clear (void)
936 {
937 // Make sure we have been initialized properly.
938 assert (m_pHeader != NULL);
939
940 // Easy enough.
941 Erase (Begin(), End());
942
943 // Since there are no nodes left, it's OK to "fix the dice" at
944 // zero again.
945 m_nHeaderLevel = 0;
946 }
947
948
949
950 // Remove an item from another skip list and insert it into ourselves.
951 // Just like an Erase() followed by an Insert(), except that there's no
952 // possibility of the operation failing.
953 template <class KEY, class VALUE, class KEYFN, class PRED,
954 int HC, class ALLOC>
955 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::InsertResult
Move(SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> & a_rOther,Iterator a_oHere)956 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Move
957 (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther, Iterator a_oHere)
958 {
959 Node *pNode;
960 // The node we're moving.
961 int16_t nLevel;
962 // The level of the node we're moving.
963 InsertResult oInsertResult;
964 // The result of the insertion.
965
966 // Make sure we're intact.
967 #ifdef DEBUG_SKIPLIST
968 Invariant();
969 #endif // DEBUG_SKIPLIST
970
971 // Make sure we have been initialized properly.
972 assert (m_pHeader != NULL);
973
974 // Make sure the skip-lists can move items between themselves.
975 assert (CanMove (a_rOther));
976
977 // Don't let them move End().
978 assert (a_oHere.m_pNode != a_rOther.m_pHeader);
979
980 // Get a reference to the key of the value being moved.
981 const KEY &rKey = m_oKeyFn (a_oHere.m_pNode->m_oValue);
982
983 // Find where to put this key. (Put equal keys at the upper bound.)
984 SearchUpper (rKey, m_pSearchFinger);
985
986 // Move this node if there's no duplicate already in here.
987 if (m_bAllowDuplicates
988 || (pNode = m_pSearchFinger->m_apForward[0],
989 pNode == m_pHeader
990 || m_oPred (m_oKeyFn (pNode->m_oValue), rKey)))
991 {
992 bool bFound;
993 // true if this node was found in the other skip list.
994
995 // Make sure the other list is intact.
996 #ifdef DEBUG_SKIPLIST
997 a_rOther.Invariant();
998 #endif // DEBUG_SKIPLIST
999
1000 // Find this node in the other skip list.
1001 bFound = a_rOther.SearchExact (a_oHere.m_pNode,
1002 a_rOther.m_pSearchFinger);
1003
1004 // Make sure this iterator points to a current node.
1005 assert (bFound);
1006
1007 // Remove it from that skip list.
1008 pNode = a_rOther.RemoveNode (a_oHere.m_pNode,
1009 a_rOther.m_pSearchFinger, &nLevel);
1010
1011 // If the node we're about to add is a higher level than any
1012 // node we've seen so far, keep track of the new maximum.
1013 if (m_nHeaderLevel < nLevel)
1014 m_nHeaderLevel = nLevel;
1015
1016 // Put it into the skip list here.
1017 InsertNode (pNode, nLevel, m_pSearchFinger);
1018
1019 // Let them know where we put it, and that we did insert it.
1020 oInsertResult.m_itPosition = Iterator (pNode);
1021 oInsertResult.m_bInserted = true;
1022 }
1023 else
1024 {
1025 // We didn't insert it. Show them the equal item.
1026 oInsertResult.m_itPosition = Iterator (pNode);
1027 oInsertResult.m_bInserted = false;
1028 }
1029
1030 // Make sure we're intact.
1031 #ifdef DEBUG_SKIPLIST
1032 Invariant();
1033 #endif // DEBUG_SKIPLIST
1034
1035 // Let them know what happened.
1036 return oInsertResult;
1037 }
1038
1039
1040
1041 // Remove a range of items from another skip-list and insert them
1042 // into ourselves.
1043 // Just like an Erase() followed by an Insert(), except that there's no
1044 // possibility of the operation failing.
1045 template <class KEY, class VALUE, class KEYFN, class PRED,
1046 int HC, class ALLOC>
1047 void
Move(SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> & a_rOther,Iterator a_oFirst,Iterator a_oLast)1048 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Move
1049 (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther, Iterator a_oFirst,
1050 Iterator a_oLast)
1051 {
1052 Iterator oHere, oNext;
1053 // The item we're moving.
1054
1055 // Make sure we have been initialized properly.
1056 assert (m_pHeader != NULL);
1057
1058 // Loop through all the items, move each one.
1059 oHere = a_oFirst;
1060 while (oHere != a_oLast)
1061 {
1062 // Keep track of the next item to move.
1063 oNext = oHere;
1064 oNext++;
1065
1066 // Move this item.
1067 Move (a_rOther, oHere);
1068
1069 // Loop back and move the next one.
1070 oHere = oNext;
1071 }
1072 }
1073
1074
1075
1076 // Move all items from the other skip-list to ourself.
1077 template <class KEY, class VALUE, class KEYFN, class PRED,
1078 int HC, class ALLOC>
1079 void
Move(SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> & a_rOther)1080 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Move
1081 (SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther)
1082 {
1083 Node *p;
1084 // Used to swap structures.
1085
1086 // Make sure we're all intact.
1087 #ifdef DEBUG_SKIPLIST
1088 Invariant();
1089 a_rOther.Invariant();
1090 #endif // DEBUG_SKIPLIST
1091
1092 // Make sure the skip-lists can move items between themselves.
1093 assert (CanMove (a_rOther));
1094
1095 // Make sure we're empty.
1096 assert (m_nItems == 0);
1097
1098 // Swap the header & search fingers.
1099 p = m_pHeader;
1100 m_pHeader = a_rOther.m_pHeader;
1101 a_rOther.m_pHeader = p;
1102 p = m_pSearchFinger;
1103 m_pSearchFinger = a_rOther.m_pSearchFinger;
1104 a_rOther.m_pSearchFinger = p;
1105 p = m_pSearchFinger2;
1106 m_pSearchFinger2 = a_rOther.m_pSearchFinger2;
1107 a_rOther.m_pSearchFinger2 = p;
1108
1109 // Use their header level, if it's bigger than ours.
1110 if (m_nHeaderLevel < a_rOther.m_nHeaderLevel)
1111 m_nHeaderLevel = a_rOther.m_nHeaderLevel;
1112 a_rOther.m_nHeaderLevel = 0;
1113
1114 // Now we have all their items.
1115 m_nItems = a_rOther.m_nItems;
1116 a_rOther.m_nItems = 0;
1117
1118 // Make sure we're all intact.
1119 #ifdef DEBUG_SKIPLIST
1120 Invariant();
1121 a_rOther.Invariant();
1122 #endif // DEBUG_SKIPLIST
1123 }
1124
1125
1126
1127 // Returns true if the two skip lists can move items between
1128 // each other.
1129 template <class KEY, class VALUE, class KEYFN, class PRED,
1130 int HC, class ALLOC>
1131 bool
CanMove(const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> & a_rOther) const1132 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::CanMove
1133 (const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther) const
1134 {
1135 // They can if they have the same allocator.
1136 return (&m_rNodeAllocator == &a_rOther.m_rNodeAllocator);
1137 }
1138
1139
1140
1141 // Assign the contents of the other skip list to ourselves.
1142 template <class KEY, class VALUE, class KEYFN, class PRED,
1143 int HC, class ALLOC>
1144 void
Assign(Status_t & a_reStatus,const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> & a_rOther)1145 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Assign (Status_t &a_reStatus,
1146 const SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC> &a_rOther)
1147 {
1148 Node *pBegin, *pEnd;
1149 // Where we're looking in the other list.
1150 Node *pHere;
1151 // Where we're looking in our list.
1152
1153 // Make sure we're intact.
1154 #ifdef DEBUG_SKIPLIST
1155 Invariant();
1156 #endif // DEBUG_SKIPLIST
1157
1158 // Make sure they didn't start us off with an error.
1159 assert (a_reStatus == g_kNoError);
1160
1161 // Make sure we have been initialized properly.
1162 assert (m_pHeader != NULL);
1163
1164 // Get the range of items from the other list.
1165 pBegin = a_rOther.Begin().m_pNode;
1166 pEnd = a_rOther.End().m_pNode;
1167
1168 // First, if we have more nodes than they do, erase enough of ours
1169 // so that we have the same amount.
1170 if (Size() > a_rOther.Size())
1171 {
1172 // Calculate the number of nodes to delete.
1173 int32_t nToDelete = Size() - a_rOther.Size();
1174
1175 // Move forward that many items.
1176 Iterator oToDelete = Begin();
1177 while (--nToDelete >= 0)
1178 oToDelete++;
1179
1180 // Delete those items.
1181 Erase (Begin(), oToDelete);
1182 }
1183
1184 // Start modifying our items here.
1185 pHere = Begin().m_pNode;
1186
1187 // Next, insert as many items as we can, using the nodes already
1188 // allocated in the list.
1189 while (pHere != m_pHeader && pBegin != pEnd)
1190 {
1191 // Store the new item over the old one.
1192 pHere->m_oValue = pBegin->m_oValue;
1193
1194 // Move forward.
1195 pHere = pHere->m_apForward[0];
1196 pBegin = pBegin->m_apForward[0];
1197 }
1198
1199 // If we ran out of nodes, insert the rest in the normal way.
1200 if (pBegin != pEnd)
1201 Insert (a_reStatus, ConstIterator (pBegin),
1202 ConstIterator (pEnd));
1203
1204 // Make sure we're intact.
1205 #ifdef DEBUG_SKIPLIST
1206 Invariant();
1207 #endif // DEBUG_SKIPLIST
1208 }
1209
1210
1211
1212 // Find the given item in the list. Returns End() if not found.
1213 template <class KEY, class VALUE, class KEYFN, class PRED,
1214 int HC, class ALLOC>
1215 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
Find(const KEY & a_rKey)1216 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Find (const KEY &a_rKey)
1217 {
1218 Iterator oHere;
1219 // What we found.
1220
1221 // Make sure we're intact.
1222 #ifdef DEBUG_SKIPLIST
1223 Invariant();
1224 #endif // DEBUG_SKIPLIST
1225
1226 // Make sure we have been initialized properly.
1227 assert (m_pHeader != NULL);
1228
1229 // Look for the item.
1230 oHere = LowerBound (a_rKey);
1231
1232 // LowerBound() returns the first item >= the key. So if this item
1233 // is greater than what they were asking for, that means we didn't
1234 // find it.
1235 if (oHere == End()
1236 || m_oPred (a_rKey, m_oKeyFn (oHere.m_pNode->m_oValue)))
1237 return End();
1238 else
1239 return oHere;
1240 }
1241
1242
1243
1244 // Find the given item in the list. Returns End() if not found.
1245 template <class KEY, class VALUE, class KEYFN, class PRED,
1246 int HC, class ALLOC>
1247 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::ConstIterator
Find(const KEY & a_rKey) const1248 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Find (const KEY &a_rKey) const
1249 {
1250 ConstIterator oHere;
1251 // What we found.
1252
1253 // Make sure we're intact.
1254 #ifdef DEBUG_SKIPLIST
1255 Invariant();
1256 #endif // DEBUG_SKIPLIST
1257
1258 // Make sure we have been initialized properly.
1259 assert (m_pHeader != NULL);
1260
1261 // Look for the item.
1262 oHere = LowerBound (a_rKey);
1263
1264 // LowerBound() returns the first item >= the key. So if this item
1265 // is greater than what they were asking for, that means we didn't
1266 // find it.
1267 if (oHere == End()
1268 || m_oPred (a_rKey, m_oKeyFn (oHere.m_pNode->m_oValue)))
1269 return End();
1270 else
1271 return oHere;
1272 }
1273
1274
1275
1276 // Return the position of the first item that's >= the key.
1277 template <class KEY, class VALUE, class KEYFN, class PRED,
1278 int HC, class ALLOC>
1279 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
LowerBound(const KEY & a_rKey)1280 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::LowerBound (const KEY &a_rKey)
1281 {
1282 // Make sure we have been initialized properly.
1283 assert (m_pHeader != NULL);
1284
1285 // Search for the first item >= the key.
1286 SearchLower (a_rKey, m_pSearchFinger);
1287
1288 // Return what we found.
1289 return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]);
1290 }
1291
1292
1293
1294 // Return the position of the first item that's >= the key.
1295 template <class KEY, class VALUE, class KEYFN, class PRED,
1296 int HC, class ALLOC>
1297 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::ConstIterator
LowerBound(const KEY & a_rKey) const1298 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::LowerBound (const KEY &a_rKey)
1299 const
1300 {
1301 // Make sure we have been initialized properly.
1302 assert (m_pHeader != NULL);
1303
1304 // Search for the first item >= the key.
1305 SearchLower (a_rKey, m_pSearchFinger);
1306
1307 // Return what we found.
1308 return ConstIterator (m_pSearchFinger->m_apForward[0]
1309 ->m_apForward[0]);
1310 }
1311
1312
1313
1314 // Return the position of the first item that's > the key.
1315 template <class KEY, class VALUE, class KEYFN, class PRED,
1316 int HC, class ALLOC>
1317 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Iterator
UpperBound(const KEY & a_rKey)1318 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::UpperBound (const KEY &a_rKey)
1319 {
1320 // Make sure we have been initialized properly.
1321 assert (m_pHeader != NULL);
1322
1323 // Search for the first item > the key.
1324 SearchUpper (a_rKey, m_pSearchFinger);
1325
1326 // Return what we found.
1327 return Iterator (m_pSearchFinger->m_apForward[0]->m_apForward[0]);
1328 }
1329
1330
1331
1332 // Return the position of the first item that's > the key.
1333 template <class KEY, class VALUE, class KEYFN, class PRED,
1334 int HC, class ALLOC>
1335 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::ConstIterator
UpperBound(const KEY & a_rKey) const1336 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::UpperBound (const KEY &a_rKey)
1337 const
1338 {
1339 // Make sure we have been initialized properly.
1340 assert (m_pHeader != NULL);
1341
1342 // Search for the first item > the key.
1343 SearchUpper (a_rKey, m_pSearchFinger);
1344
1345 // Return what we found.
1346 return ConstIterator (m_pSearchFinger->m_apForward[0]
1347 ->m_apForward[0]);
1348 }
1349
1350
1351
1352 // Return the size of the largest possible skip-list node.
1353 template <class KEY, class VALUE, class KEYFN, class PRED,
1354 int HC, class ALLOC>
1355 size_t
GetSizeOfLargestNode(void) const1356 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::GetSizeOfLargestNode (void) const
1357 {
1358 // Easy enough.
1359 return (size_t)(&(((Node *)0x80000000)->m_apForward[HEADERCHUNK]))
1360 - 0x80000000;
1361 }
1362
1363
1364
1365 // Search for an item greater than or equal to a_rKey.
1366 template <class KEY, class VALUE, class KEYFN, class PRED,
1367 int HC, class ALLOC>
1368 void
SearchLower(const KEY & a_rKey,Node * a_pTraverse) const1369 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SearchLower (const KEY &a_rKey,
1370 Node *a_pTraverse) const
1371 {
1372 Node *pCurrentNode;
1373 // Where we're searching.
1374 int16_t nCurrentLevel;
1375 // The level we've searched so far.
1376 Node *pLastFinger;
1377 // A node that we know is < the key.
1378 Node *pAlreadyChecked;
1379 // A node that we know is >= the key.
1380
1381 // Make sure we're intact.
1382 #ifdef DEBUG_SKIPLIST
1383 Invariant();
1384 #endif // DEBUG_SKIPLIST
1385
1386 // Make sure we have been initialized properly.
1387 assert (m_pHeader != NULL);
1388
1389 // See how much of the previous search we can reuse.
1390 pCurrentNode = m_pHeader;
1391 pLastFinger = m_pHeader;
1392 pAlreadyChecked = m_pHeader;
1393 nCurrentLevel = m_nHeaderLevel;
1394 while (--nCurrentLevel >= 0)
1395 {
1396 Node *pCurrentFinger;
1397 // What's at this level.
1398
1399 // See what's at this level.
1400 pCurrentFinger = a_pTraverse->m_apForward[nCurrentLevel];
1401
1402 // If this is what we found before, OR if there's nothing here,
1403 // OR we haven't gone past what we're trying to find, then
1404 // there's a chance we can reuse the search at this level.
1405 if (pCurrentFinger == pLastFinger
1406 || pCurrentFinger == m_pHeader
1407 || m_oPred (m_oKeyFn (pCurrentFinger->m_oValue), a_rKey))
1408 {
1409 // Look at the item past the current search finger.
1410 Node *pNextFinger
1411 = pCurrentFinger->m_apForward[nCurrentLevel];
1412
1413 // If there's nothing here, OR what's here is >= what we're
1414 // looking for, then we can reuse all of this level's
1415 // search.
1416 if (pNextFinger == m_pHeader
1417 || pNextFinger == pAlreadyChecked
1418 || !m_oPred (m_oKeyFn (pNextFinger->m_oValue), a_rKey))
1419 {
1420 // We can reuse all of this level's search.
1421 pCurrentNode = pCurrentFinger;
1422 pLastFinger = pCurrentFinger;
1423 pAlreadyChecked = pNextFinger;
1424 }
1425 else
1426 {
1427 // We can reuse this level's search, but we have to
1428 // start looking here.
1429 pCurrentNode = pCurrentFinger;
1430 nCurrentLevel++;
1431 break;
1432 }
1433 }
1434 else
1435 {
1436 // We can't reuse this level. Redo it.
1437 nCurrentLevel++;
1438 break;
1439 }
1440 }
1441
1442 // Now search for the item in the list.
1443 while (--nCurrentLevel >= 0)
1444 {
1445 Node *pNextNode;
1446 while (pNextNode = pCurrentNode->m_apForward[nCurrentLevel],
1447 pNextNode != pAlreadyChecked && pNextNode != m_pHeader
1448 && m_oPred (m_oKeyFn (pNextNode->m_oValue), a_rKey))
1449 {
1450 pCurrentNode = pNextNode;
1451 }
1452 pAlreadyChecked = pCurrentNode->m_apForward[nCurrentLevel];
1453 a_pTraverse->m_apForward[nCurrentLevel] = pCurrentNode;
1454 }
1455
1456 // Make sure we're intact.
1457 #ifdef DEBUG_SKIPLIST
1458 Invariant();
1459 #endif // DEBUG_SKIPLIST
1460 }
1461
1462
1463
1464 // Search for this exact item. Returns true if it's found.
1465 template <class KEY, class VALUE, class KEYFN, class PRED,
1466 int HC, class ALLOC>
1467 bool
SearchExact(Node * a_pKey,Node * a_pTraverse) const1468 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SearchExact (Node *a_pKey,
1469 Node *a_pTraverse) const
1470 {
1471 Node *pFound;
1472 // What we found.
1473 int16_t nI;
1474 // Used to iterate through levels.
1475
1476 // Make sure we're intact.
1477 #ifdef DEBUG_SKIPLIST
1478 Invariant();
1479 #endif // DEBUG_SKIPLIST
1480
1481 // Make sure we have been initialized properly.
1482 assert (m_pHeader != NULL);
1483
1484 // If they passed us End(), just search to the end and succeed.
1485 if (a_pKey == m_pHeader)
1486 {
1487 SearchEnd (a_pTraverse);
1488 return true;
1489 }
1490
1491 // Find the lower bound.
1492 SearchLower (m_oKeyFn (a_pKey->m_oValue), a_pTraverse);
1493
1494 // Run through the equal range, look for this exact item.
1495 for (pFound = a_pTraverse->m_apForward[0]->m_apForward[0];
1496 pFound != m_pHeader && pFound != a_pKey;
1497 pFound = pFound->m_apForward[0])
1498 {
1499 // Advance the search finger.
1500 for (nI = 0;
1501 nI < m_nHeaderLevel
1502 && a_pTraverse->m_apForward[nI]->m_apForward[nI]
1503 == pFound;
1504 nI++)
1505 {
1506 a_pTraverse->m_apForward[nI] = pFound;
1507 }
1508 }
1509
1510 // Make sure we're intact.
1511 #ifdef DEBUG_SKIPLIST
1512 Invariant();
1513 #endif // DEBUG_SKIPLIST
1514
1515 // Let them know if we succeeded.
1516 return (pFound == a_pKey);
1517 }
1518
1519
1520
1521 // Search for an item greater than a_rKey.
1522 template <class KEY, class VALUE, class KEYFN, class PRED,
1523 int HC, class ALLOC>
1524 void
SearchUpper(const KEY & a_rKey,Node * a_pTraverse) const1525 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SearchUpper (const KEY &a_rKey,
1526 Node *a_pTraverse) const
1527 {
1528 Node *pCurrentNode;
1529 // Where we're searching.
1530 int16_t nCurrentLevel;
1531 // The level we've searched so far.
1532 Node *pLastFinger;
1533 // A node that we know is <= the key.
1534 Node *pAlreadyChecked;
1535 // A node that we know is > the key.
1536
1537 // Make sure we're intact.
1538 #ifdef DEBUG_SKIPLIST
1539 Invariant();
1540 #endif // DEBUG_SKIPLIST
1541
1542 // Make sure we have been initialized properly.
1543 assert (m_pHeader != NULL);
1544
1545 // See how much of the previous search we can reuse.
1546 pCurrentNode = m_pHeader;
1547 pLastFinger = m_pHeader;
1548 pAlreadyChecked = m_pHeader;
1549 nCurrentLevel = m_nHeaderLevel;
1550 while (--nCurrentLevel >= 0)
1551 {
1552 Node *pCurrentFinger;
1553 // What's at this level.
1554
1555 // See what's at this level.
1556 pCurrentFinger = a_pTraverse->m_apForward[nCurrentLevel];
1557
1558 // If this is what we found before, OR if there's nothing here,
1559 // OR we haven't gone past what we're trying to find, then
1560 // there's a chance we can reuse the search at this level.
1561 if (pCurrentFinger == pLastFinger
1562 || pCurrentFinger == m_pHeader
1563 || !m_oPred (a_rKey, m_oKeyFn (pCurrentFinger->m_oValue)))
1564 {
1565 // Look at the item past the current search finger.
1566 Node *pNextFinger
1567 = pCurrentFinger->m_apForward[nCurrentLevel];
1568
1569 // If there's nothing here, OR what's here is > what we're
1570 // looking for, then we can reuse all of this level's
1571 // search.
1572 if (pNextFinger == m_pHeader
1573 || pNextFinger == pAlreadyChecked
1574 || m_oPred (a_rKey, m_oKeyFn (pNextFinger->m_oValue)))
1575 {
1576 // We can reuse all of this level's search.
1577 pCurrentNode = pCurrentFinger;
1578 pLastFinger = pCurrentFinger;
1579 pAlreadyChecked = pNextFinger;
1580 }
1581 else
1582 {
1583 // We can reuse this level's search, but we have to
1584 // start looking here.
1585 pCurrentNode = pCurrentFinger;
1586 nCurrentLevel++;
1587 break;
1588 }
1589 }
1590 else
1591 {
1592 // We can't reuse this level. Redo it.
1593 nCurrentLevel++;
1594 break;
1595 }
1596 }
1597
1598 // Now search for the item in the list.
1599 while (--nCurrentLevel >= 0)
1600 {
1601 Node *pNextNode;
1602 while (pNextNode = pCurrentNode->m_apForward[nCurrentLevel],
1603 pNextNode != pAlreadyChecked && pNextNode != m_pHeader
1604 && !m_oPred (a_rKey, m_oKeyFn (pNextNode->m_oValue)))
1605 {
1606 pCurrentNode = pNextNode;
1607 }
1608 pAlreadyChecked = pCurrentNode->m_apForward[nCurrentLevel];
1609 a_pTraverse->m_apForward[nCurrentLevel] = pCurrentNode;
1610 }
1611
1612 // Make sure we're intact.
1613 #ifdef DEBUG_SKIPLIST
1614 Invariant();
1615 #endif // DEBUG_SKIPLIST
1616 }
1617
1618
1619
1620 // Point to the end of the list.
1621 template <class KEY, class VALUE, class KEYFN, class PRED,
1622 int HC, class ALLOC>
1623 void
SearchEnd(Node * a_pTraverse) const1624 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::SearchEnd (Node *a_pTraverse)
1625 const
1626 {
1627 // Make sure we have been initialized properly.
1628 assert (m_pHeader != NULL);
1629
1630 // Make sure we're intact.
1631 #ifdef DEBUG_SKIPLIST
1632 Invariant();
1633 #endif // DEBUG_SKIPLIST
1634
1635 // Point every level of the traverse array to the last node before
1636 // the end.
1637 Node *pLastNode = a_pTraverse->m_apForward[m_nHeaderLevel - 1];
1638 int16_t nCurrentLevel = m_nHeaderLevel;
1639 while (--nCurrentLevel >= 0)
1640 {
1641 Node *pNextNode;
1642 while (pNextNode = pLastNode->m_apForward[nCurrentLevel],
1643 pNextNode != m_pHeader)
1644 {
1645 pLastNode = pNextNode;
1646 }
1647 a_pTraverse->m_apForward[nCurrentLevel] = pLastNode;
1648 }
1649
1650 // Make sure we're intact.
1651 #ifdef DEBUG_SKIPLIST
1652 Invariant();
1653 #endif // DEBUG_SKIPLIST
1654 }
1655
1656
1657
1658 // Insert a new node into the skip list. Assume a_pTraverse is
1659 // set up.
1660 template <class KEY, class VALUE, class KEYFN, class PRED,
1661 int HC, class ALLOC>
1662 void
InsertNode(Node * a_pNewNode,int16_t a_nNewLevel,Node * a_pTraverse)1663 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::InsertNode (Node *a_pNewNode,
1664 int16_t a_nNewLevel, Node *a_pTraverse)
1665 {
1666 // Make sure we're intact.
1667 #ifdef DEBUG_SKIPLIST
1668 Invariant();
1669 #endif // DEBUG_SKIPLIST
1670
1671 // Set up the backward link of the new node.
1672 a_pNewNode->m_pBackward = a_pTraverse->m_apForward[0];
1673
1674 // Modify all levels of pointers.
1675 while (--a_nNewLevel >= 0)
1676 {
1677 // Insert ourselves where the traverse array points.
1678 a_pNewNode->m_apForward[a_nNewLevel]
1679 = a_pTraverse->m_apForward[a_nNewLevel]
1680 ->m_apForward[a_nNewLevel];
1681 a_pTraverse->m_apForward[a_nNewLevel]->m_apForward[a_nNewLevel]
1682 = a_pNewNode;
1683
1684 // Point the traverse array at the new node.
1685 a_pTraverse->m_apForward[a_nNewLevel] = a_pNewNode;
1686 }
1687
1688 // Set up the backward link of the node after the new one.
1689 a_pNewNode->m_apForward[0]->m_pBackward = a_pNewNode;
1690
1691 // That's one more node in the list.
1692 m_nItems++;
1693
1694 // Make sure we're intact.
1695 #ifdef DEBUG_SKIPLIST
1696 Invariant();
1697 #endif // DEBUG_SKIPLIST
1698 }
1699
1700
1701
1702 // Remove the given node from the skip list. Assume a_pTraverse is
1703 // set up.
1704 // Returns the node that got removed, and optionally backpatches its
1705 // level.
1706 template <class KEY, class VALUE, class KEYFN, class PRED,
1707 int HC, class ALLOC>
1708 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Node *
RemoveNode(Node * a_pToRemove,Node * a_pTraverse,int16_t * a_pLevel)1709 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::RemoveNode (Node *a_pToRemove,
1710 Node *a_pTraverse, int16_t *a_pLevel)
1711 {
1712 int16_t nI;
1713 // Used to loop through skip-list levels.
1714 Node *pCurrentNode;
1715 // A node that's pointing to the node we're removing.
1716
1717 // Make sure we're intact.
1718 #ifdef DEBUG_SKIPLIST
1719 Invariant();
1720 #endif // DEBUG_SKIPLIST
1721
1722 // Make sure this traversal array is set up to remove this node.
1723 assert (a_pTraverse->m_apForward[0]->m_apForward[0] == a_pToRemove);
1724
1725 // Remove this node from all levels where it appears.
1726 for (nI = 0;
1727 nI < m_nHeaderLevel
1728 && (pCurrentNode = a_pTraverse->m_apForward[nI],
1729 pCurrentNode->m_apForward[nI] == a_pToRemove);
1730 nI++)
1731 {
1732 pCurrentNode->m_apForward[nI] = a_pToRemove->m_apForward[nI];
1733 }
1734
1735 // Make sure the node had as many levels as we expected.
1736 #ifdef DEBUG_SKIPLIST
1737 assert (nI == a_pToRemove->m_nLevel);
1738 #endif // DEBUG_SKIPLIST
1739
1740 // Remove this node from the back-links.
1741 a_pTraverse->m_apForward[0]->m_apForward[0]->m_pBackward
1742 = a_pTraverse->m_apForward[0];
1743
1744 // That's one less item in the list.
1745 m_nItems--;
1746
1747 // Give them the level of this node, if they asked for it.
1748 if (a_pLevel != NULL)
1749 *a_pLevel = nI;
1750
1751 // Make sure we're intact.
1752 #ifdef DEBUG_SKIPLIST
1753 Invariant();
1754 #endif // DEBUG_SKIPLIST
1755
1756 // Return the node we removed.
1757 return a_pToRemove;
1758 }
1759
1760
1761
1762 // Allocate a new node with the given number of forward pointers.
1763 // Returns NULL if something goes wrong.
1764 template <class KEY, class VALUE, class KEYFN, class PRED,
1765 int HC, class ALLOC>
1766 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Node *
GetNewNode(int16_t a_nForwardPointers)1767 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::GetNewNode
1768 (int16_t a_nForwardPointers)
1769 {
1770 size_t nBytes;
1771 // The number of bytes this node needs.
1772 Node *pNode;
1773 // The node we allocate.
1774
1775 // Calculate the number of bytes it takes to represent a node with
1776 // this many forward pointers.
1777 nBytes = (size_t)(&(((Node *)0x80000000)
1778 ->m_apForward[a_nForwardPointers])) - 0x80000000;
1779
1780 // Allocate space.
1781 pNode = (Node *) m_rNodeAllocator.Allocate (a_nForwardPointers - 1,
1782 nBytes);
1783 if (pNode == NULL)
1784 return NULL;
1785
1786 // Set the number of forward pointers.
1787 #ifdef DEBUG_SKIPLIST
1788 pNode->m_nLevel = a_nForwardPointers;
1789 #endif // DEBUG_SKIPLIST
1790
1791 // Return what we allocated.
1792 return pNode;
1793 }
1794
1795
1796
1797 // Allocate a new node with a random number of forward pointers.
1798 // Returns NULL if something goes wrong; otherwise, a_rnLevel gets
1799 // backpatched with the number of levels.
1800 template <class KEY, class VALUE, class KEYFN, class PRED,
1801 int HC, class ALLOC>
1802 typename SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Node *
GetNewNodeOfRandomLevel(int16_t & a_rnLevel)1803 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::GetNewNodeOfRandomLevel
1804 (int16_t &a_rnLevel)
1805 {
1806 // Fix the dice (as described in the skip-list paper).
1807 int16_t nHighestLevel = (m_nHeaderLevel == HEADERCHUNK)
1808 ? HEADERCHUNK : (m_nHeaderLevel + 1);
1809
1810 // Now generate a random level for the node. (12055 / 32768 equals
1811 // our skip list's p, which is 1/e.)
1812 int16_t nNewLevel = 1;
1813 while (nNewLevel < nHighestLevel && Rand() < 12055)
1814 nNewLevel++;
1815
1816 // Keep track of the new maximum.
1817 if (nNewLevel == nHighestLevel)
1818 m_nHeaderLevel = nHighestLevel;
1819
1820 // Allocate a node of this size.
1821 a_rnLevel = nNewLevel;
1822 return GetNewNode (nNewLevel);
1823 }
1824
1825
1826
1827 // Delete a node.
1828 template <class KEY, class VALUE, class KEYFN, class PRED,
1829 int HC, class ALLOC>
1830 void
DeleteNode(int16_t a_nForwardPointers,Node * a_pToDelete)1831 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::DeleteNode
1832 (int16_t a_nForwardPointers, Node *a_pToDelete)
1833 {
1834 // Make sure they gave us a node to delete.
1835 assert (a_pToDelete != NULL);
1836
1837 // Delete the value we contain.
1838 a_pToDelete->m_oValue.~VALUE();
1839
1840 // Deallocate the node's storage.
1841 DeallocateNode (a_nForwardPointers, a_pToDelete);
1842 }
1843
1844
1845
1846 // Deallocate a node's storage.
1847 template <class KEY, class VALUE, class KEYFN, class PRED,
1848 int HC, class ALLOC>
1849 void
DeallocateNode(int16_t a_nForwardPointers,Node * a_pToDelete)1850 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::DeallocateNode
1851 (int16_t a_nForwardPointers, Node *a_pToDelete)
1852 {
1853 // Make sure they gave us a node to deallocate.
1854 assert (a_pToDelete != NULL);
1855
1856 // Calculate the number of bytes it takes to represent a node with
1857 // this many forward pointers.
1858 size_t nBytes = (size_t)(&(((Node *)0x80000000)
1859 ->m_apForward[a_nForwardPointers])) - 0x80000000;
1860
1861 // Return the memory to our node allocator.
1862 m_rNodeAllocator.Deallocate (a_nForwardPointers - 1,
1863 nBytes, (void *)a_pToDelete);
1864 }
1865
1866
1867
1868 // Get another random number.
1869 template <class KEY, class VALUE, class KEYFN, class PRED,
1870 int HC, class ALLOC>
1871 int16_t
Rand(void)1872 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Rand (void)
1873 {
1874 // I'd use the normal rand() but it's WAAAY too slow.
1875 // Feel free to adjust this routine all you want.
1876 m_nRandSeed = m_nRandSeed * 42989 + 17891;
1877 return int16_t (m_nRandSeed & 32767);
1878 }
1879
1880
1881
1882 #ifdef DEBUG_SKIPLIST
1883
1884 template <class KEY, class VALUE, class KEYFN, class PRED,
1885 int HC, class ALLOC>
1886 void
Invariant(void) const1887 SkipList<KEY,VALUE,KEYFN,PRED,HC,ALLOC>::Invariant (void) const
1888 {
1889 int32_t nI;
1890 // Used to loop through things.
1891 Node *pSearchFinger;
1892 // Used to verify the integrity of the forward pointers.
1893 Node *pCurrentNode;
1894 // The node whose integrity we are presently verifying.
1895 Node *pPreviousNode;
1896 // The node before the current one.
1897 uint32_t nItems;
1898 // The number of items we found.
1899
1900 // Only check the invariant if they requested we do.
1901 if (!m_bDebug)
1902 return;
1903
1904 // If the skip list is not fully initialized, we have less to check.
1905 if (m_pHeader == NULL)
1906 {
1907 assert (m_nHeaderLevel == 0);
1908 assert (m_pSearchFinger == NULL);
1909 assert (m_pSearchFinger2 == NULL);
1910 assert (m_nItems == 0);
1911 return;
1912 }
1913
1914 // Make sure the skip list level isn't bigger than the compiled-in
1915 // maximum.
1916 assert (m_nHeaderLevel <= HEADERCHUNK);
1917
1918 // Calculate the number of bytes it takes to represent a node with
1919 // this many forward pointers.
1920 size_t nBytes = (size_t)(&(((Node *)0x80000000)
1921 ->m_apForward[HEADERCHUNK])) - 0x80000000;
1922
1923 // We're going to run through the skip list and make sure all the
1924 // forward pointers are correct. For that, we need a temporary
1925 // search finger to keep track of the traversal.
1926 pSearchFinger = (Node *) alloca (nBytes);
1927 pSearchFinger->m_nLevel = 0;
1928 pSearchFinger->m_pBackward = NULL;
1929 for (nI = 0; nI < HEADERCHUNK; nI++)
1930 pSearchFinger->m_apForward[nI] = m_pHeader;
1931
1932 // The backward link for the header node points to the last item in
1933 // the list. So find the last item in the list.
1934 pPreviousNode = m_pHeader;
1935 while (pPreviousNode->m_apForward[0] != m_pHeader)
1936 pPreviousNode = pPreviousNode->m_apForward[0];
1937
1938 // Run through the skip list, make sure the forward pointers and
1939 // backward pointers are intact.
1940 pCurrentNode = m_pHeader;
1941 nItems = 0;
1942 for (;;)
1943 {
1944 int32_t nLevel;
1945 // The level of the current node.
1946
1947 // At least one forward pointer of the temporary search finger
1948 // points to the current node. The number of forward pointers
1949 // that point to the current node, must be equal to its assigned
1950 // level. So start by calculating what level this node must be.
1951 nLevel = 0;
1952 while (nLevel < HEADERCHUNK
1953 && pSearchFinger->m_apForward[nLevel] == pCurrentNode)
1954 nLevel++;
1955
1956 // Make sure the node has that many forward pointers.
1957 assert (pCurrentNode->m_nLevel == nLevel);
1958
1959 // Make sure the backward pointer is intact.
1960 assert (pCurrentNode->m_pBackward == pPreviousNode);
1961
1962 // Make sure that the nodes are in proper sorted order.
1963 if (pPreviousNode != m_pHeader && pCurrentNode != m_pHeader)
1964 {
1965 if (m_bAllowDuplicates)
1966 {
1967 // The current item has to be >= the previous item.
1968 assert (!m_oPred (m_oKeyFn (pCurrentNode->m_oValue),
1969 m_oKeyFn (pPreviousNode->m_oValue)));
1970 }
1971 else
1972 {
1973 // The current item has to be > the previous item.
1974 assert (m_oPred (m_oKeyFn (pPreviousNode->m_oValue),
1975 m_oKeyFn (pCurrentNode->m_oValue)));
1976 }
1977 }
1978
1979 // If we're at the end of the list, stop.
1980 if (pCurrentNode->m_apForward[0] == m_pHeader)
1981 break;
1982
1983 // That's one more item we found. (We put this here in order to
1984 // avoid counting the header node as an item.)
1985 nItems++;
1986
1987 // Move forward.
1988 pPreviousNode = pCurrentNode;
1989 pCurrentNode = pCurrentNode->m_apForward[0];
1990 for (nI = 0; nI < nLevel; nI++)
1991 pSearchFinger->m_apForward[nI]
1992 = pSearchFinger->m_apForward[nI]->m_apForward[nI];
1993 }
1994
1995 // Make sure the list has the expected number of items.
1996 assert (m_nItems == nItems);
1997 }
1998
1999 #endif // DEBUG_SKIPLIST
2000
2001
2002
2003 #endif // __SKIPLIST_H__
2004