39#include "common/math/random_generator.h"
40#include "common/lang/atomic.h"
41#include "common/lang/vector.h"
42#include "common/log/log.h"
46template <
typename Key,
class ObComparator>
68 void insert_concurrently(
const Key &key);
98 const Key &
key()
const;
140 inline int get_max_height()
const {
return max_height_.load(std::memory_order_relaxed); }
142 Node *new_node(
const Key &key,
int height);
144 bool equal(
const Key &a,
const Key &b)
const {
return (compare_(a, b) == 0); }
151 Node *find_greater_or_equal(
const Key &key,
Node **prev)
const;
155 Node *find_less_than(
const Key &key)
const;
159 Node *find_last()
const;
162 ObComparator
const compare_;
168 atomic<int> max_height_;
173template <
typename Key,
class ObComparator>
177template <
typename Key,
class ObComparator>
180 explicit Node(
const Key &k) : key(k) {}
188 ASSERT(n >= 0,
"n >= 0");
191 return next_[n].load(std::memory_order_acquire);
193 void set_next(
int n,
Node *x)
195 ASSERT(n >= 0,
"n >= 0");
198 next_[n].store(x, std::memory_order_release);
202 Node *nobarrier_next(
int n)
204 ASSERT(n >= 0,
"n >= 0");
205 return next_[n].load(std::memory_order_relaxed);
207 void nobarrier_set_next(
int n,
Node *x)
209 ASSERT(n >= 0,
"n >= 0");
210 next_[n].store(x, std::memory_order_relaxed);
213 bool cas_next(
int n,
Node *expected,
Node *x)
215 ASSERT(n >= 0,
"n >= 0");
216 return next_[n].compare_exchange_strong(expected, x);
221 atomic<Node *> next_[1];
224template <
typename Key,
class ObComparator>
227 char *
const node_memory =
reinterpret_cast<char *
>(malloc(
sizeof(
Node) +
sizeof(atomic<Node *>) * (height - 1)));
228 return new (node_memory)
Node(key);
231template <
typename Key,
class ObComparator>
238template <
typename Key,
class ObComparator>
241 return node_ !=
nullptr;
244template <
typename Key,
class ObComparator>
247 ASSERT(valid(),
"valid");
251template <
typename Key,
class ObComparator>
254 ASSERT(valid(),
"valid");
255 node_ = node_->next(0);
258template <
typename Key,
class ObComparator>
263 ASSERT(valid(),
"valid");
264 node_ = list_->find_less_than(node_->key);
265 if (node_ == list_->head_) {
270template <
typename Key,
class ObComparator>
273 node_ = list_->find_greater_or_equal(target,
nullptr);
276template <
typename Key,
class ObComparator>
279 node_ = list_->head_->next(0);
282template <
typename Key,
class ObComparator>
285 node_ = list_->find_last();
286 if (node_ == list_->head_) {
291template <
typename Key,
class ObComparator>
295 static const unsigned int kBranching = 4;
297 while (height < kMaxHeight && rnd.next(kBranching) == 0) {
300 ASSERT(height > 0,
"height > 0");
301 ASSERT(height <= kMaxHeight,
"height <= kMaxHeight");
305template <
typename Key,
class ObComparator>
306typename ObSkipList<Key, ObComparator>::Node *ObSkipList<Key, ObComparator>::find_greater_or_equal(
307 const Key &key,
Node **prev)
const
313template <
typename Key,
class ObComparator>
314typename ObSkipList<Key, ObComparator>::Node *ObSkipList<Key, ObComparator>::find_less_than(
const Key &key)
const
317 int level = get_max_height() - 1;
319 ASSERT(x == head_ || compare_(x->key, key) < 0,
"x == head_ || compare_(x->key, key) < 0");
320 Node *next = x->next(level);
321 if (next ==
nullptr || compare_(next->key, key) >= 0) {
334template <
typename Key,
class ObComparator>
335typename ObSkipList<Key, ObComparator>::Node *ObSkipList<Key, ObComparator>::find_last()
const
338 int level = get_max_height() - 1;
340 Node *next = x->next(level);
341 if (next ==
nullptr) {
354template <
typename Key,
class ObComparator>
356 : compare_(cmp), head_(new_node(0 , kMaxHeight)), max_height_(1)
358 for (
int i = 0; i < kMaxHeight; i++) {
359 head_->set_next(i,
nullptr);
363template <
typename Key,
class ObComparator>
366 typename std::vector<Node *> nodes;
367 nodes.reserve(max_height_.load(std::memory_order_relaxed));
368 for (
Node *x = head_; x !=
nullptr; x = x->next(0)) {
371 for (
auto node : nodes) {
377template <
typename Key,
class ObComparator>
381template <
typename Key,
class ObComparator>
387template <
typename Key,
class ObComparator>
390 Node *x = find_greater_or_equal(key,
nullptr);
391 if (x !=
nullptr && equal(key, x->key)) {
Definition: random_generator.h:25
base class of all comparators
Definition: ob_comparator.h:21
Iteration over the contents of a skip list
Definition: ob_skiplist.h:81
void seek_to_last()
Position at the last entry in list.
Definition: ob_skiplist.h:283
void seek(const Key &target)
Advance to the first entry with a key >= target
Definition: ob_skiplist.h:271
void next()
Advance to the next entry in the list. REQUIRES: valid()
Definition: ob_skiplist.h:252
const Key & key() const
Returns the key at the current position. REQUIRES: valid()
Definition: ob_skiplist.h:245
Iterator(const ObSkipList *list)
Initialize an iterator over the specified list.
Definition: ob_skiplist.h:232
void seek_to_first()
Position at the first entry in list.
Definition: ob_skiplist.h:277
void prev()
Advances to the previous position. REQUIRES: valid()
Definition: ob_skiplist.h:259
bool valid() const
Returns true iff the iterator is positioned at a valid node.
Definition: ob_skiplist.h:239
Definition: ob_skiplist.h:48
ObSkipList(ObComparator cmp)
Create a new ObSkipList object that will use "cmp" for comparing keys.
Definition: ob_skiplist.h:355
bool contains(const Key &key) const
Returns true if an entry that compares equal to key is in the list.
Definition: ob_skiplist.h:388
void insert(const Key &key)
Insert key into the list. REQUIRES: nothing that compares equal to key is currently in the list
Definition: ob_skiplist.h:378
Definition: ob_skiplist.h:179