github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/database/leveldb.chai2010/include/db/skiplist.h (about)

     1  // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license that can be
     3  // found in the LICENSE file. See the AUTHORS file for names of contributors.
     4  //
     5  // Thread safety
     6  // -------------
     7  //
     8  // Writes require external synchronization, most likely a mutex.
     9  // Reads require a guarantee that the SkipList will not be destroyed
    10  // while the read is in progress.  Apart from that, reads progress
    11  // without any internal locking or synchronization.
    12  //
    13  // Invariants:
    14  //
    15  // (1) Allocated nodes are never deleted until the SkipList is
    16  // destroyed.  This is trivially guaranteed by the code since we
    17  // never delete any skip list nodes.
    18  //
    19  // (2) The contents of a Node except for the next/prev pointers are
    20  // immutable after the Node has been linked into the SkipList.
    21  // Only Insert() modifies the list, and it is careful to initialize
    22  // a node and use release-stores to publish the nodes in one or
    23  // more lists.
    24  //
    25  // ... prev vs. next pointer ordering ...
    26  
    27  #include <assert.h>
    28  #include <stdlib.h>
    29  #include "port/port.h"
    30  #include "util/arena.h"
    31  #include "util/random.h"
    32  
    33  namespace leveldb {
    34  
    35  class Arena;
    36  
    37  template<typename Key, class Comparator>
    38  class SkipList {
    39   private:
    40    struct Node;
    41  
    42   public:
    43    // Create a new SkipList object that will use "cmp" for comparing keys,
    44    // and will allocate memory using "*arena".  Objects allocated in the arena
    45    // must remain allocated for the lifetime of the skiplist object.
    46    explicit SkipList(Comparator cmp, Arena* arena);
    47  
    48    // Insert key into the list.
    49    // REQUIRES: nothing that compares equal to key is currently in the list.
    50    void Insert(const Key& key);
    51  
    52    // Returns true iff an entry that compares equal to key is in the list.
    53    bool Contains(const Key& key) const;
    54  
    55    // Iteration over the contents of a skip list
    56    class Iterator {
    57     public:
    58      // Initialize an iterator over the specified list.
    59      // The returned iterator is not valid.
    60      explicit Iterator(const SkipList* list);
    61  
    62      // Returns true iff the iterator is positioned at a valid node.
    63      bool Valid() const;
    64  
    65      // Returns the key at the current position.
    66      // REQUIRES: Valid()
    67      const Key& key() const;
    68  
    69      // Advances to the next position.
    70      // REQUIRES: Valid()
    71      void Next();
    72  
    73      // Advances to the previous position.
    74      // REQUIRES: Valid()
    75      void Prev();
    76  
    77      // Advance to the first entry with a key >= target
    78      void Seek(const Key& target);
    79  
    80      // Position at the first entry in list.
    81      // Final state of iterator is Valid() iff list is not empty.
    82      void SeekToFirst();
    83  
    84      // Position at the last entry in list.
    85      // Final state of iterator is Valid() iff list is not empty.
    86      void SeekToLast();
    87  
    88     private:
    89      const SkipList* list_;
    90      Node* node_;
    91      // Intentionally copyable
    92    };
    93  
    94   private:
    95    enum { kMaxHeight = 12 };
    96  
    97    // Immutable after construction
    98    Comparator const compare_;
    99    Arena* const arena_;    // Arena used for allocations of nodes
   100  
   101    Node* const head_;
   102  
   103    // Modified only by Insert().  Read racily by readers, but stale
   104    // values are ok.
   105    port::AtomicPointer max_height_;   // Height of the entire list
   106  
   107    inline int GetMaxHeight() const {
   108      return static_cast<int>(
   109          reinterpret_cast<intptr_t>(max_height_.NoBarrier_Load()));
   110    }
   111  
   112    // Read/written only by Insert().
   113    Random rnd_;
   114  
   115    Node* NewNode(const Key& key, int height);
   116    int RandomHeight();
   117    bool Equal(const Key& a, const Key& b) const { return (compare_(a, b) == 0); }
   118  
   119    // Return true if key is greater than the data stored in "n"
   120    bool KeyIsAfterNode(const Key& key, Node* n) const;
   121  
   122    // Return the earliest node that comes at or after key.
   123    // Return NULL if there is no such node.
   124    //
   125    // If prev is non-NULL, fills prev[level] with pointer to previous
   126    // node at "level" for every level in [0..max_height_-1].
   127    Node* FindGreaterOrEqual(const Key& key, Node** prev) const;
   128  
   129    // Return the latest node with a key < key.
   130    // Return head_ if there is no such node.
   131    Node* FindLessThan(const Key& key) const;
   132  
   133    // Return the last node in the list.
   134    // Return head_ if list is empty.
   135    Node* FindLast() const;
   136  
   137    // No copying allowed
   138    SkipList(const SkipList&);
   139    void operator=(const SkipList&);
   140  };
   141  
   142  // Implementation details follow
   143  template<typename Key, class Comparator>
   144  struct SkipList<Key,Comparator>::Node {
   145    explicit Node(const Key& k) : key(k) { }
   146  
   147    Key const key;
   148  
   149    // Accessors/mutators for links.  Wrapped in methods so we can
   150    // add the appropriate barriers as necessary.
   151    Node* Next(int n) {
   152      assert(n >= 0);
   153      // Use an 'acquire load' so that we observe a fully initialized
   154      // version of the returned Node.
   155      return reinterpret_cast<Node*>(next_[n].Acquire_Load());
   156    }
   157    void SetNext(int n, Node* x) {
   158      assert(n >= 0);
   159      // Use a 'release store' so that anybody who reads through this
   160      // pointer observes a fully initialized version of the inserted node.
   161      next_[n].Release_Store(x);
   162    }
   163  
   164    // No-barrier variants that can be safely used in a few locations.
   165    Node* NoBarrier_Next(int n) {
   166      assert(n >= 0);
   167      return reinterpret_cast<Node*>(next_[n].NoBarrier_Load());
   168    }
   169    void NoBarrier_SetNext(int n, Node* x) {
   170      assert(n >= 0);
   171      next_[n].NoBarrier_Store(x);
   172    }
   173  
   174   private:
   175    // Array of length equal to the node height.  next_[0] is lowest level link.
   176    port::AtomicPointer next_[1];
   177  };
   178  
   179  template<typename Key, class Comparator>
   180  typename SkipList<Key,Comparator>::Node*
   181  SkipList<Key,Comparator>::NewNode(const Key& key, int height) {
   182    char* mem = arena_->AllocateAligned(
   183        sizeof(Node) + sizeof(port::AtomicPointer) * (height - 1));
   184    return new (mem) Node(key);
   185  }
   186  
   187  template<typename Key, class Comparator>
   188  inline SkipList<Key,Comparator>::Iterator::Iterator(const SkipList* list) {
   189    list_ = list;
   190    node_ = NULL;
   191  }
   192  
   193  template<typename Key, class Comparator>
   194  inline bool SkipList<Key,Comparator>::Iterator::Valid() const {
   195    return node_ != NULL;
   196  }
   197  
   198  template<typename Key, class Comparator>
   199  inline const Key& SkipList<Key,Comparator>::Iterator::key() const {
   200    assert(Valid());
   201    return node_->key;
   202  }
   203  
   204  template<typename Key, class Comparator>
   205  inline void SkipList<Key,Comparator>::Iterator::Next() {
   206    assert(Valid());
   207    node_ = node_->Next(0);
   208  }
   209  
   210  template<typename Key, class Comparator>
   211  inline void SkipList<Key,Comparator>::Iterator::Prev() {
   212    // Instead of using explicit "prev" links, we just search for the
   213    // last node that falls before key.
   214    assert(Valid());
   215    node_ = list_->FindLessThan(node_->key);
   216    if (node_ == list_->head_) {
   217      node_ = NULL;
   218    }
   219  }
   220  
   221  template<typename Key, class Comparator>
   222  inline void SkipList<Key,Comparator>::Iterator::Seek(const Key& target) {
   223    node_ = list_->FindGreaterOrEqual(target, NULL);
   224  }
   225  
   226  template<typename Key, class Comparator>
   227  inline void SkipList<Key,Comparator>::Iterator::SeekToFirst() {
   228    node_ = list_->head_->Next(0);
   229  }
   230  
   231  template<typename Key, class Comparator>
   232  inline void SkipList<Key,Comparator>::Iterator::SeekToLast() {
   233    node_ = list_->FindLast();
   234    if (node_ == list_->head_) {
   235      node_ = NULL;
   236    }
   237  }
   238  
   239  template<typename Key, class Comparator>
   240  int SkipList<Key,Comparator>::RandomHeight() {
   241    // Increase height with probability 1 in kBranching
   242    static const unsigned int kBranching = 4;
   243    int height = 1;
   244    while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0)) {
   245      height++;
   246    }
   247    assert(height > 0);
   248    assert(height <= kMaxHeight);
   249    return height;
   250  }
   251  
   252  template<typename Key, class Comparator>
   253  bool SkipList<Key,Comparator>::KeyIsAfterNode(const Key& key, Node* n) const {
   254    // NULL n is considered infinite
   255    return (n != NULL) && (compare_(n->key, key) < 0);
   256  }
   257  
   258  template<typename Key, class Comparator>
   259  typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindGreaterOrEqual(const Key& key, Node** prev)
   260      const {
   261    Node* x = head_;
   262    int level = GetMaxHeight() - 1;
   263    while (true) {
   264      Node* next = x->Next(level);
   265      if (KeyIsAfterNode(key, next)) {
   266        // Keep searching in this list
   267        x = next;
   268      } else {
   269        if (prev != NULL) prev[level] = x;
   270        if (level == 0) {
   271          return next;
   272        } else {
   273          // Switch to next list
   274          level--;
   275        }
   276      }
   277    }
   278  }
   279  
   280  template<typename Key, class Comparator>
   281  typename SkipList<Key,Comparator>::Node*
   282  SkipList<Key,Comparator>::FindLessThan(const Key& key) const {
   283    Node* x = head_;
   284    int level = GetMaxHeight() - 1;
   285    while (true) {
   286      assert(x == head_ || compare_(x->key, key) < 0);
   287      Node* next = x->Next(level);
   288      if (next == NULL || compare_(next->key, key) >= 0) {
   289        if (level == 0) {
   290          return x;
   291        } else {
   292          // Switch to next list
   293          level--;
   294        }
   295      } else {
   296        x = next;
   297      }
   298    }
   299  }
   300  
   301  template<typename Key, class Comparator>
   302  typename SkipList<Key,Comparator>::Node* SkipList<Key,Comparator>::FindLast()
   303      const {
   304    Node* x = head_;
   305    int level = GetMaxHeight() - 1;
   306    while (true) {
   307      Node* next = x->Next(level);
   308      if (next == NULL) {
   309        if (level == 0) {
   310          return x;
   311        } else {
   312          // Switch to next list
   313          level--;
   314        }
   315      } else {
   316        x = next;
   317      }
   318    }
   319  }
   320  
   321  template<typename Key, class Comparator>
   322  SkipList<Key,Comparator>::SkipList(Comparator cmp, Arena* arena)
   323      : compare_(cmp),
   324        arena_(arena),
   325        head_(NewNode(0 /* any key will do */, kMaxHeight)),
   326        max_height_(reinterpret_cast<void*>(1)),
   327        rnd_(0xdeadbeef) {
   328    for (int i = 0; i < kMaxHeight; i++) {
   329      head_->SetNext(i, NULL);
   330    }
   331  }
   332  
   333  template<typename Key, class Comparator>
   334  void SkipList<Key,Comparator>::Insert(const Key& key) {
   335    // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual()
   336    // here since Insert() is externally synchronized.
   337    Node* prev[kMaxHeight];
   338    Node* x = FindGreaterOrEqual(key, prev);
   339  
   340    // Our data structure does not allow duplicate insertion
   341    assert(x == NULL || !Equal(key, x->key));
   342  
   343    int height = RandomHeight();
   344    if (height > GetMaxHeight()) {
   345      for (int i = GetMaxHeight(); i < height; i++) {
   346        prev[i] = head_;
   347      }
   348      //fprintf(stderr, "Change height from %d to %d\n", max_height_, height);
   349  
   350      // It is ok to mutate max_height_ without any synchronization
   351      // with concurrent readers.  A concurrent reader that observes
   352      // the new value of max_height_ will see either the old value of
   353      // new level pointers from head_ (NULL), or a new value set in
   354      // the loop below.  In the former case the reader will
   355      // immediately drop to the next level since NULL sorts after all
   356      // keys.  In the latter case the reader will use the new node.
   357      max_height_.NoBarrier_Store(reinterpret_cast<void*>(height));
   358    }
   359  
   360    x = NewNode(key, height);
   361    for (int i = 0; i < height; i++) {
   362      // NoBarrier_SetNext() suffices since we will add a barrier when
   363      // we publish a pointer to "x" in prev[i].
   364      x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i));
   365      prev[i]->SetNext(i, x);
   366    }
   367  }
   368  
   369  template<typename Key, class Comparator>
   370  bool SkipList<Key,Comparator>::Contains(const Key& key) const {
   371    Node* x = FindGreaterOrEqual(key, NULL);
   372    if (x != NULL && Equal(key, x->key)) {
   373      return true;
   374    } else {
   375      return false;
   376    }
   377  }
   378  
   379  }  // namespace leveldb