Skiplist principle of Leveldb source code

Source: Internet
Author: User
Tags assert bool prev sorts

Feel skiplist as long as the height is clear. The following is a function of the randomly generated height randomheight ()

Template<typename Key, class comparator>
int skiplist<key,comparator>::randomheight () {
  // Increase height with probability 1 in kbranching
  static const unsigned int kbranching = 4;
  int height = 1;
  while (Height < kmaxheight && (rnd_. Next ()% kbranching) = = 0) {
    height++;
  }
  ASSERT (height > 0);
  ASSERT (height <= kmaxheight);
  return height;
}

Insert operation:

Template<typename Key, class comparator> void Skiplist<key,comparator>::insert (const key& Key) {//TODO (opt): We can use a barrier-free (shielded, barrier/barrier-free) variant of findgreaterorequal ()//here since Insert () is externally sy
  Nchronized.
  Prev for each layer of the front node node* prev[kmaxheight];

  Find the inserted node node* x = Findgreaterorequal (key, prev); Our data structure does isn't allow duplicate insertion assert (x = = NULL | |!
  Equal (key, X->key));
  Randomly generated node height int height = randomheight ();
    if (Height > getmaxheight ()) {for (int i = Getmaxheight (); i < height; i++) {prev[i] = Head_;

    }//fprintf (stderr, "change height from%d to%d\n", max_height_, height);  It is ok to mutate max_height_ without a synchronization//with concurrent readers. A concurrent reader that observes//the new value of Max_height_ would see either the old value of//new level PO  Inters from Head_ (NULL), or a new value set in//the loop below. In THe former case the reader would//immediately drop to the next level since NULL sorts after all//keys.
    The latter case the reader would use the new node. Sets the maximum height max_height_.
  Nobarrier_store (reinterpret_cast<void*> (height));
  }//Generate a new node x = NewNode (key, height); for (int i = 0; i < height; i++) {//Nobarrier_setnext () suffices since we'll add a barrier when//we publi
    SH A pointer to "X" in Prev[i].
    X->nobarrier_setnext (i, Prev[i]->nobarrier_next (i));
  Prev[i]->setnext (i, x); }
}
Find an operation:

Template<typename Key, class comparator>
TypeName skiplist<key,comparator>::node* Skiplist<key, Comparator>::findgreaterorequal (const key& Key, node** prev)
    const {
  node* x = head_;
  Find
  int level = Getmaxheight ()-1
  , starting at the top while (true) {
    node* next = X->next (level);
    Look to the right
    if (Keyisafternode (key, Next)) {
      //Keep searching in this list
      x = next;
    } else {
    	//down lookup 
  if (prev! = NULL) Prev[level] = x;
      if (level = = 0) {
        return next;
      } else {
        //Switch to Next list
        level--;}
}}}
Whole SkipList.h Source:

Copyright (c) the LevelDB Authors.
All rights reserved. Use of this source code was governed by a Bsd-style license, can be//found in the license file.
See the AUTHORS file for names of contributors.
Thread Safety//-------------////writes require external synchronization, most likely a mutex.  Reads require a guarantee that the skiplist would not being destroyed//while the read was in progress.
Apart from this, reads progress//without any internal locking or synchronization.  Invariants:////(1) allocated nodes is never deleted until the skiplist is//destroyed.
This is trivially guaranteed by the code since we//never delete any skip list nodes. (2) The contents of a node except for the Next/prev pointers is//immutable after the node have been linked into th
E skiplist. Only Insert () modifies the list, and it's careful to initialize//a node and use Release-stores to publish the nodes
In one or/+ more lists. ... prev vs. nextPointer ordering #include <assert.h> #include <stdlib.h> #include "port/port.h" #include "util/arena.h" # Include "Util/random.h"/** * skiplist apply probabilities to ensure balance, balanced tree with strict rotation to ensure balance * Use skiplist Yes find specific time complexity is O (Logn), with the balance tree has the same complexity, save space,

Average 1.33 pointers per inspection * Leveldb The highest number of layers is 12, only inserts and modifications are allowed, the record key is not allowed to repeat, add a sequene Num * Specification: Parameters use a reference, the return value uses the pointer * */namespace Leveldb {

Class Arena;

 Template<typename Key, Class comparator> class Skiplist {private:struct Node; Public://Create A new Skiplist object that would use "CMP" for comparing keys,//and would allocate memory using "*ar  Ena ".
  Objects allocated in the arena//must remain allocated for the lifetime of the Skiplist object.

  Explicit Skiplist (Comparator cmp, arena* Arena);
  Insert key into the list.
  Requires:nothing that compares equal to key are currently in the list.

  void Insert (const key& Key);
  Returns true iff an entry, compares equal to key are in the list. BOOL Contains (const key& Key) Const Iteration over the contents of a skip list class Iterator {public://Initialize an Iterator over the Specifi
    Ed List.
    The returned iterator is not valid.

    Explicit Iterator (const skiplist* list);
    Returns true iff the iterator is positioned at a valid node.

    BOOL Valid () const;
    Returns the key at the current position.

    Requires:valid () const key& Key () const;
    Advances to the next position.

    Requires:valid () void Next ();
    Advances to the previous position.

    Requires:valid () void Prev ();

    Advance to the first entry with a key >= target void Seek (const key& target);
    Position at the first entry in list.
    Final state of Iterator was Valid () IFF list is not empty.

    void Seektofirst ();
    Position at the last entry in list.
    Final state of Iterator was Valid () IFF list is not empty.

   void Seektolast ();
  Private:const skiplist* List_;  node* Node_;

  Intentionally copyable};

  The highest level of the hop table Private:enum {kmaxheight = 12};
  Immutable (immutable) after construction Comparator const compare_;    Stage, arena, place (memory pool only for application space) arena* const Arena_;

  Arena used for allocations of nodes node* Const HEAD_;  Modified only by Insert ().
  Read racily by readers, but stale//values is OK.   Port::atomicpointer Max_height_; Height of the entire list inline int getmaxheight () const {return static_cast<int> (reinterpret_c Ast<intptr_t> (Max_height_.
  Nobarrier_load ()));
  }//Read/written only by Insert ().

  Random Rnd_;
  node* NewNode (const key& Key, int height);
  int Randomheight ();

  BOOL Equal (const key& A, const key& b) Const {return (Compare_ (A, b) = = 0);}

  Return true if key is greater than the data stored in "n" bool Keyisafternode (const key& key, node* N) const;
  Return The earliest node that is comes at or after key. Return NULL If there is no such node. If prev is non-null, fills Prev[level] with pointer to previous//node at "level" for every level in [0..max_he
  IGHT_-1].

  node* findgreaterorequal (const key& Key, node** prev) const;
  Return the latest node with a key < key.
  Return Head_ If there is no such node.

  node* Findlessthan (const key& Key) const;
  Return the last node in the list.
  Return Head_ if list is empty.

  node* FindLast () const;
  No copying allowed skiplist (const skiplist&);
void operator= (const skiplist&);

}; Implementation details follow Template<typename Key, class comparator> struct skiplist<key,comparator>::

  Node {explicit node (const key& K): Key (k) {} Key const key;  Accessors/mutators for links.
  Wrapped in methods so we can//add the appropriate barriers as necessary.
    node* Next (int n) {assert (n >= 0); Use the ' acquire load ' so that we observe a fully initialized//VErsion of the returned Node. Return reinterpret_cast<node*> (Next_[n].
  Acquire_load ());
    } void Setnext (int n, node* x) {assert (n >= 0);  Use a ' release store ' So, anybody who reads through this//pointer observes a fully initialized version of the
    Inserted node. Next_[n].
  Release_store (x);
  }//No-barrier variants that can is safely used in a few locations.
    node* Nobarrier_next (int n) {assert (n >= 0); Return reinterpret_cast<node*> (Next_[n].
  Nobarrier_load ());
    } void Nobarrier_setnext (int n, node* x) {assert (n >= 0); Next_[n].
  Nobarrier_store (x);  } private://Array of length equal to the node height.
  NEXT_[0] is lowest level link.
Port::atomicpointer Next_[1];

}; Template<typename Key, Class Comparator> TypeName skiplist<key,comparator>::node* Skiplist<key, Comparator>::newnode (const key& Key, int height) {char* mem = arena_->allocatealigned (sizeof (Node) + s) Izeof (PORt::atomicpointer) * (height-1));
return new (MEM) Node (key); } template<typename Key, class comparator> inline Skiplist<key,comparator>::iterator::iterator (const
  skiplist* list) {list_ = list;
Node_ = NULL;
  } template<typename Key, class comparator>, inline bool Skiplist<key,comparator>::iterator::valid () const {
return node_! = NULL; } template<typename Key, class comparator>, inline const key& Skiplist<key,comparator>::iterator::key ()
  const {ASSERT (Valid ());
Return node_->key; } template<typename Key, class comparator>, inline void Skiplist<key,comparator>::iterator::next () {ASSERT (
  Valid ());
Node_ = Node_->next (0); } template<typename Key, class comparator>, inline void Skiplist<key,comparator>::iterator::P rev () {//Inst
  EAD of using explicit "prev" links, we just search for the//last node that falls before key.
  ASSERT (Valid ());
  Node_ = List_->findlessthan (Node_->key); if (nOde_ = = List_->head_) {node_ = NULL; }} Template<typename key, class comparator> inline void Skiplist<key,comparator>::iterator::seek (const key

& target) {Node_ = List_->findgreaterorequal (target, NULL);}
  Template<typename Key, class comparator>, inline void Skiplist<key,comparator>::iterator::seektofirst () {
Node_ = List_->head_->next (0); } template<typename Key, class comparator>, inline void Skiplist<key,comparator>::iterator::seektolast () {n
  Ode_ = List_->findlast ();
  if (Node_ = = list_->head_) {node_ = NULL; }} template<typename Key, class comparator> int skiplist<key,comparator>::randomheight () {//Increase Hei
  Ght with probability 1 in kbranching static const unsigned int kbranching = 4;
  int height = 1; while (Height < kmaxheight && (rnd_.
  Next ()% kbranching) = = 0) {height++;
  } assert (height > 0);
  ASSERT (height <= kmaxheight);
return height;

}Template<typename key, Class comparator> bool Skiplist<key,comparator>::keyisafternode (const Key& Key 
, node* N) const {//null n is considered infinite return (n! = NULL) && (Compare_ (N->key, key) < 0);} /** * Find, from left to right, find from top to bottom */template<typename Key, Class Comparator> TypeName skiplist<key,comparator>::node* S
  Kiplist<key,comparator>::findgreaterorequal (const key& Key, node** prev) const {node* x = Head_;
  find int level = Getmaxheight ()-1, starting at the top
    while (true) {node* next = X->next (level);
    Look to the right if (Keyisafternode (key, Next)) {//Keep searching in this list x = Next;
      } else {//Look down if (prev! = NULL) Prev[level] = x;
      if (level = = 0) {return next;
      } else {//Switch to next list level--; }}}} Template<typename Key, class Comparator> TypeName skiplist<key,comparator>::node* skiplist<k Ey,comparator>::finDlessthan (const key& Key) Const {node* x = Head_;
  int level = Getmaxheight ()-1;
    while (true) {assert (x = = Head_ | | compare_ (X-&GT;KEY, key) < 0);
    node* next = X->next (level);
      if (next = NULL | | compare_ (NEXT-&GT;KEY, key) >= 0) {if (level = = 0) {return x;
      } else {//Switch to next list level--;
    }} else {x = next; }}} Template<typename Key, class Comparator> TypeName skiplist<key,comparator>::node* skiplist<key,com
  Parator>::findlast () const {node* x = Head_;
  int level = Getmaxheight ()-1;
    while (true) {node* next = X->next (level);
      if (next = = NULL) {if (level = = 0) {return x;
      } else {//Switch to next list level--;
    }} else {x = next; }}}/** * skiplist initialization * */Template<typename Key, class comparator> skiplist<key,comparator>::skiplist (
  Comparator CMP, arena* Arena)  : Compare_ (CMP), Arena_ (Arena), Head_ (NewNode (0 */any key would do */, Kmaxheight)), Max_height_ (reint Erpret_cast<void*> (1)), Rnd_ (0xdeadbeef) {for (int i = 0; i < kmaxheight; i++) {Head_->setnext (i
  , NULL); }}/** * Insert a new Key * */template<typename key, class comparator> void Skiplist<key,comparator>::insert (con St key& Key) {//TODO (OPT): We can use a barrier-free (shield, barrier/barrier-free) variant of findgreaterorequal ()//Here Sin
  Ce Insert () is externally synchronized.
  Prev for each layer of the front node node* prev[kmaxheight];

  Find the inserted node node* x = Findgreaterorequal (key, prev); Our data structure does isn't allow duplicate insertion assert (x = = NULL | |!
  Equal (key, X->key));
  Randomly generated node height int height = randomheight ();
    if (Height > getmaxheight ()) {for (int i = Getmaxheight (); i < height; i++) {prev[i] = Head_;

    }//fprintf (stderr, "change height from%d to%d\n", max_height_, height); It is OK to mutate Max_height_ without a synchronization//with concurrent readers. A concurrent reader that observes//the new value of Max_height_ would see either the old value of//new level PO  Inters from Head_ (NULL), or a new value set in//the loop below.  In the former case the reader would//immediately drop to the next level since NULL sorts after all//keys.
    The latter case the reader would use the new node. Sets the maximum height max_height_.
  Nobarrier_store (reinterpret_cast<void*> (height));
  }//Generate a new node x = NewNode (key, height); for (int i = 0; i < height; i++) {//Nobarrier_setnext () suffices since we'll add a barrier when//we publi
    SH A pointer to "X" in Prev[i].
    X->nobarrier_setnext (i, Prev[i]->nobarrier_next (i));
  Prev[i]->setnext (i, x); }}/** * includes */Template<typename Key, class comparator> bool Skiplist<key,comparator>::contains (const KEY&A mp Key) const {node* x = findgreateroreqUAL (key, NULL);
  if (x! = NULL && Equal (Key, X->key)) {return true;
  } else {return false;
 }}}//Namespace Leveldb




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.