public: // Create a new SkipList object that will use "cmp" for comparing keys, // and will allocate memory using "*arena". Objects allocated in the arena // must remain allocated for the lifetime of the skiplist object. explicitSkipList(Comparator cmp, Arena* arena);
// Insert key into the list. // REQUIRES: nothing that compares equal to key is currently in the list. voidInsert(const Key& key);
// Returns true iff an entry that compares equal to key is in the list. boolContains(const Key& key)const;
// Iteration over the contents of a skip list classIterator { public: // Initialize an iterator over the specified list. // The returned iterator is not valid. explicitIterator(const SkipList* list);
// Returns true iff the iterator is positioned at a valid node. boolValid()const;
// Returns the key at the current position. // REQUIRES: Valid() const Key& key()const;
// Advances to the next position. // REQUIRES: Valid() voidNext();
// Advances to the previous position. // REQUIRES: Valid() voidPrev();
// Advance to the first entry with a key >= target voidSeek(const Key& target);
// Position at the first entry in list. // Final state of iterator is Valid() iff list is not empty. voidSeekToFirst();
// Position at the last entry in list. // Final state of iterator is Valid() iff list is not empty. voidSeekToLast();
Node* NewNode(const Key& key, int height); intRandomHeight(); boolEqual(const Key& a, const Key& b)const{ return (compare_(a, b) == 0); }
// Return true if key is greater than the data stored in "n" boolKeyIsAfterNode(const Key& key, Node* n)const;
// Return the earliest node that comes at or after key. // Return nullptr 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_height_-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;
// Immutable after construction Comparator const compare_; Arena* const arena_; // Arena used for allocations of nodes
Node* const head_;
// Modified only by Insert(). Read racily by readers, but stale // values are ok. std::atomic<int> max_height_; // Height of the entire list
template <typename Key, classComparator> void SkipList<Key, Comparator>::Insert(const Key& key) { // TODO(opt): We can use a barrier-free variant of FindGreaterOrEqual() // here since Insert() is externally synchronized. Node* prev[kMaxHeight]; Node* x = FindGreaterOrEqual(key, prev);
// Our data structure does not allow duplicate insertion //leveldb跳表要求不能插入重复数据 assert(x == nullptr || !Equal(key, x->key));
int height = RandomHeight(); //随机获取一个level值 if (height > GetMaxHeight()) { //GetMaxHeight为获取跳表当前高度 for (int i = GetMaxHeight(); i < height; i++) { prev[i] = head_; } // It is ok to mutate max_height_ without any synchronization // with concurrent readers. A concurrent reader that observes // the new value of max_height_ will see either the old value of // new level pointers from head_ (nullptr), or a new value set in // the loop below. In the former case the reader will // immediately drop to the next level since nullptr sorts after all // keys. In the latter case the reader will use the new node. // 此处不用为并发读加锁。因为并发读在(在另外线程中通过 FindGreaterOrEqual 中的 GetMaxHeight) // 读取到更新后跳表层数,但该节点尚未插入时也无妨。因为这意味着它会读到 nullptr,而在 LevelDB // 的 Comparator 设定中,nullptr 比所有 key 都大。因此,FindGreaterOrEqual 会继续往下找, // 符合预期。 max_height_.store(height, std::memory_order_relaxed); }
x = NewNode(key, height); for (int i = 0; i < height; i++) { // NoBarrier_SetNext() suffices since we will add a barrier when // we publish a pointer to "x" in prev[i]. // 此句 NoBarrier_SetNext() 版本就够用了,因为后续 prev[i]->SetNext(i, x) 语句会进行强制同步。 // 并且为了保证并发读的正确性,一定要先设置本节点指针,再设置原条表中节点(prev)指针 x->NoBarrier_SetNext(i, prev[i]->NoBarrier_Next(i)); prev[i]->SetNext(i, x); } }
// Iteration over the contents of a skip list classIterator { public: // Initialize an iterator over the specified list. // The returned iterator is not valid. explicitIterator(const SkipList* list);
// Returns true iff the iterator is positioned at a valid node. boolValid()const;
// Returns the key at the current position. // REQUIRES: Valid() const Key& key()const;
// Advances to the next position. // REQUIRES: Valid() voidNext();
// Advances to the previous position. // REQUIRES: Valid() voidPrev();
// Advance to the first entry with a key >= target voidSeek(const Key& target);
// Position at the first entry in list. // Final state of iterator is Valid() iff list is not empty. voidSeekToFirst();
// Position at the last entry in list. // Final state of iterator is Valid() iff list is not empty. voidSeekToLast();