@ -45,6 +45,7 @@
# include <stdlib.h>
# include <algorithm>
# include <atomic>
# include "port/likely.h"
# include "port/port.h"
# include "util/allocator.h"
# include "util/random.h"
@ -81,7 +82,7 @@ class InlineSkipList {
//
// REQUIRES: nothing that compares equal to key is currently in the list.
// REQUIRES: no concurrent calls to any of inserts.
void Insert ( const char * key ) ;
bool Insert ( const char * key ) ;
// Inserts a key allocated by AllocateKey with a hint of last insert
// position in the skip-list. If hint points to nullptr, a new hint will be
@ -93,10 +94,10 @@ class InlineSkipList {
//
// REQUIRES: nothing that compares equal to key is currently in the list.
// REQUIRES: no concurrent calls to any of inserts.
void InsertWithHint ( const char * key , void * * hint ) ;
bool InsertWithHint ( const char * key , void * * hint ) ;
// Like Insert, but external synchronization is not required.
void InsertConcurrently ( const char * key ) ;
bool InsertConcurrently ( const char * key ) ;
// Inserts a node into the skip list. key must have been allocated by
// AllocateKey and then filled in by the caller. If UseCAS is true,
@ -114,7 +115,7 @@ class InlineSkipList {
// false has worse running time for the non-sequential case O(log N),
// but a better constant factor.
template < bool UseCAS >
void Insert ( const char * key , Splice * splice , bool allow_partial_splice_fix ) ;
bool Insert ( const char * key , Splice * splice , bool allow_partial_splice_fix ) ;
// Returns true iff an entry that compares equal to key is in the list.
bool Contains ( const char * key ) const ;
@ -626,29 +627,29 @@ InlineSkipList<Comparator>::AllocateSplice() {
}
template < class Comparator >
void InlineSkipList < Comparator > : : Insert ( const char * key ) {
Insert < false > ( key , seq_splice_ , false ) ;
bool InlineSkipList < Comparator > : : Insert ( const char * key ) {
return Insert < false > ( key , seq_splice_ , false ) ;
}
template < class Comparator >
void InlineSkipList < Comparator > : : InsertConcurrently ( const char * key ) {
bool InlineSkipList < Comparator > : : InsertConcurrently ( const char * key ) {
Node * prev [ kMaxPossibleHeight ] ;
Node * next [ kMaxPossibleHeight ] ;
Splice splice ;
splice . prev_ = prev ;
splice . next_ = next ;
Insert < true > ( key , & splice , false ) ;
return Insert < true > ( key , & splice , false ) ;
}
template < class Comparator >
void InlineSkipList < Comparator > : : InsertWithHint ( const char * key , void * * hint ) {
bool InlineSkipList < Comparator > : : InsertWithHint ( const char * key , void * * hint ) {
assert ( hint ! = nullptr ) ;
Splice * splice = reinterpret_cast < Splice * > ( * hint ) ;
if ( splice = = nullptr ) {
splice = AllocateSplice ( ) ;
* hint = reinterpret_cast < void * > ( splice ) ;
}
Insert < false > ( key , splice , true ) ;
return Insert < false > ( key , splice , true ) ;
}
template < class Comparator >
@ -694,7 +695,7 @@ void InlineSkipList<Comparator>::RecomputeSpliceLevels(const char* key,
template < class Comparator >
template < bool UseCAS >
void InlineSkipList < Comparator > : : Insert ( const char * key , Splice * splice ,
bool InlineSkipList < Comparator > : : Insert ( const char * key , Splice * splice ,
bool allow_partial_splice_fix ) {
Node * x = reinterpret_cast < Node * > ( const_cast < char * > ( key ) ) - 1 ;
int height = x - > UnstashHeight ( ) ;
@ -801,6 +802,17 @@ void InlineSkipList<Comparator>::Insert(const char* key, Splice* splice,
if ( UseCAS ) {
for ( int i = 0 ; i < height ; + + i ) {
while ( true ) {
// Checking for duplicate keys on the level 0 is sufficient
if ( UNLIKELY ( i = = 0 & & splice - > next_ [ i ] ! = nullptr & &
compare_ ( x - > Key ( ) , splice - > next_ [ i ] - > Key ( ) ) > = 0 ) ) {
// duplicate key
return false ;
}
if ( UNLIKELY ( i = = 0 & & splice - > prev_ [ i ] ! = head_ & &
compare_ ( splice - > prev_ [ i ] - > Key ( ) , x - > Key ( ) ) > = 0 ) ) {
// duplicate key
return false ;
}
assert ( splice - > next_ [ i ] = = nullptr | |
compare_ ( x - > Key ( ) , splice - > next_ [ i ] - > Key ( ) ) < 0 ) ;
assert ( splice - > prev_ [ i ] = = head_ | |
@ -833,6 +845,17 @@ void InlineSkipList<Comparator>::Insert(const char* key, Splice* splice,
FindSpliceForLevel < false > ( key , splice - > prev_ [ i ] , nullptr , i , & splice - > prev_ [ i ] ,
& splice - > next_ [ i ] ) ;
}
// Checking for duplicate keys on the level 0 is sufficient
if ( UNLIKELY ( i = = 0 & & splice - > next_ [ i ] ! = nullptr & &
compare_ ( x - > Key ( ) , splice - > next_ [ i ] - > Key ( ) ) > = 0 ) ) {
// duplicate key
return false ;
}
if ( UNLIKELY ( i = = 0 & & splice - > prev_ [ i ] ! = head_ & &
compare_ ( splice - > prev_ [ i ] - > Key ( ) , x - > Key ( ) ) > = 0 ) ) {
// duplicate key
return false ;
}
assert ( splice - > next_ [ i ] = = nullptr | |
compare_ ( x - > Key ( ) , splice - > next_ [ i ] - > Key ( ) ) < 0 ) ;
assert ( splice - > prev_ [ i ] = = head_ | |
@ -865,6 +888,7 @@ void InlineSkipList<Comparator>::Insert(const char* key, Splice* splice,
} else {
splice - > height_ = 0 ;
}
return true ;
}
template < class Comparator >