126 #include <type_traits> 128 #include <boost/iterator/iterator_facade.hpp> 129 #include <glog/logging.h> 140 typename Comp = std::less<T>,
143 typename NodeAlloc = SysAllocator<void>,
150 MAX_HEIGHT >= 2 && MAX_HEIGHT < 64,
151 "MAX_HEIGHT can only be in the range of [2, 64)");
152 typedef std::unique_lock<folly::MicroSpinLock>
ScopedLocker;
188 const NodeAlloc& alloc) {
189 return std::make_shared<ConcurrentSkipList>(
height, alloc);
193 return std::make_shared<ConcurrentSkipList>(
height);
207 NodeType* tmp =
current->skip(0);
214 static bool greater(
const value_type&
data,
const NodeType* node) {
215 return node && Comp()(node->
data(),
data);
218 static bool less(
const value_type&
data,
const NodeType* node) {
219 return (node ==
nullptr) || Comp()(
data, node->
data());
225 const value_type&
data,
229 NodeType* pred = cur;
230 NodeType* foundNode =
nullptr;
231 for (
int layer = cur_layer; layer >= 0; --layer) {
232 NodeType* node = pred->
skip(layer);
235 node = node->
skip(layer);
237 if (foundLayer == -1 && !
less(data, node)) {
246 succs[layer] = foundNode ? foundNode : node;
252 return size_.load(std::memory_order_relaxed);
256 return head_.load(std::memory_order_consume)->height();
264 return size_.fetch_add(delta, std::memory_order_relaxed) + delta;
270 if (ret.second && !ret.first->markedForRemoval()) {
281 ScopedLocker guards[MAX_HEIGHT],
282 NodeType* preds[MAX_HEIGHT],
283 NodeType* succs[MAX_HEIGHT],
284 bool adding =
true) {
285 NodeType *pred, *succ, *prevPred =
nullptr;
287 for (
int layer = 0; valid && layer < nodeHeight; ++layer) {
289 DCHECK(pred !=
nullptr) <<
"layer=" << layer <<
" height=" <<
height()
290 <<
" nodeheight=" << nodeHeight;
292 if (pred != prevPred) {
297 pred->
skip(layer) == succ;
313 template <
typename U>
315 NodeType *preds[MAX_HEIGHT], *succs[MAX_HEIGHT];
323 NodeType* nodeFound = succs[layer];
324 DCHECK(nodeFound !=
nullptr);
331 return std::make_pair(nodeFound, 0);
338 ScopedLocker guards[MAX_HEIGHT];
346 for (
int k = 0;
k < nodeHeight; ++
k) {
360 if (hgt < MAX_HEIGHT && newSize > sizeLimit) {
363 CHECK_GT(newSize, 0);
364 return std::make_pair(newNode, newSize);
367 bool remove(
const value_type&
data) {
368 NodeType* nodeToDelete =
nullptr;
369 ScopedLocker nodeGuard;
370 bool isMarked =
false;
372 NodeType *preds[MAX_HEIGHT], *succs[MAX_HEIGHT];
377 if (!isMarked && (layer < 0 || !
okToDelete(succs[layer], layer))) {
382 nodeToDelete = succs[layer];
383 nodeHeight = nodeToDelete->
height();
393 ScopedLocker guards[MAX_HEIGHT];
398 for (
int k = nodeHeight - 1;
k >= 0; --
k) {
410 auto node =
head_.load(std::memory_order_consume)->skip(0);
411 return node ? &node->data() :
nullptr;
414 const value_type*
last()
const {
415 NodeType* pred =
head_.load(std::memory_order_consume);
416 NodeType* node =
nullptr;
417 for (
int layer =
maxLayer(); layer >= 0; --layer) {
419 node = pred->
skip(layer);
423 }
while (node !=
nullptr);
425 return pred ==
head_.load(std::memory_order_relaxed) ?
nullptr 430 DCHECK(candidate !=
nullptr);
437 const value_type&
data,
440 int* max_layer)
const {
443 head_.load(std::memory_order_consume), *max_layer,
data, preds, succs);
459 NodeType* pred =
head_.load(std::memory_order_consume);
461 NodeType* node =
nullptr;
466 for (; ht > 0 &&
less(data, node = pred->
skip(ht - 1)); --ht) {
469 return std::make_pair(node, 0);
477 node = node->
skip(ht);
479 found = !
less(data, node);
481 return std::make_pair(node, found);
487 NodeType* pred =
head_.load(std::memory_order_consume);
488 NodeType* node =
nullptr;
491 for (
int layer =
top; !found && layer >= 0; --layer) {
492 node = pred->
skip(layer);
495 node = node->
skip(layer);
497 found = !
less(data, node);
499 return std::make_pair(node, found);
504 while (node !=
nullptr && node->markedForRemoval()) {
505 node = node->skip(0);
511 NodeType* oldHead =
head_.load(std::memory_order_consume);
523 NodeType* expected = oldHead;
524 if (!
head_.compare_exchange_strong(
525 expected, newHead, std::memory_order_release)) {
544 template <
typename T,
typename Comp,
typename NodeAlloc,
int MAX_HEIGHT>
564 explicit Accessor(std::shared_ptr<ConcurrentSkipList> skip_list)
565 : slHolder_(
std::
move(skip_list)) {
566 sl_ = slHolder_.get();
567 DCHECK(sl_ !=
nullptr);
568 sl_->recycler_.addRef();
574 DCHECK(sl_ !=
nullptr);
575 sl_->recycler_.addRef();
579 : sl_(accessor.sl_), slHolder_(accessor.slHolder_) {
580 sl_->recycler_.addRef();
584 if (
this != &accessor) {
586 sl_->recycler_.releaseRef();
594 sl_->recycler_.releaseRef();
598 return sl_->size() == 0;
621 NodeType* head = sl_->head_.load(std::memory_order_consume);
639 auto ret = sl_->addOrGetData(std::forward<U>(
data));
640 return std::make_pair(
iterator(ret.first), ret.second);
647 return iterator(sl_->lower_bound(data));
651 return sl_->height();
678 auto last = sl_->last();
679 return last ? sl_->remove(*
last) :
false;
683 auto ret = sl_->addOrGetData(data);
684 return std::make_pair(&ret.first->data(), ret.second);
696 return sl_->find(data);
699 return sl_->addOrGetData(data).second;
701 bool remove(
const key_type&
data) {
702 return sl_->remove(
data);
711 template <
typename ValT,
typename NodeT>
713 csl_iterator<ValT, NodeT>,
715 boost::forward_traversal_tag> {
724 template <
typename OtherVal,
typename OtherNode>
727 typename std::enable_if<
729 : node_(other.node_) {}
732 return node_ ==
nullptr ? 0
733 : node_->height() *
sizeof(NodeT*) +
sizeof(*
this);
737 return node_ !=
nullptr;
741 friend class boost::iterator_core_access;
742 template <
class,
class>
746 node_ = node_->next();
749 return node_ == other.
node_;
752 return node_->data();
759 template <
typename T,
typename Comp,
typename NodeAlloc,
int MAX_HEIGHT>
771 Skipper(
const std::shared_ptr<SkipListType>& skipList) : accessor_(skipList) {
775 Skipper(
const Accessor& accessor) : accessor_(accessor) {
781 NodeType* head_node = head();
782 headHeight_ = head_node->
height();
783 for (
int i = 0;
i < headHeight_; ++
i) {
784 preds_[
i] = head_node;
785 succs_[
i] = head_node->
skip(
i);
788 for (
int i = 0;
i < max_layer; ++
i) {
791 hints_[max_layer] = max_layer;
796 preds_[0] = succs_[0];
797 succs_[0] = preds_[0]->skip(0);
799 for (
int i = 1;
i < height && preds_[0] == succs_[
i]; ++
i) {
800 preds_[
i] = succs_[
i];
801 succs_[
i] = preds_[
i]->skip(
i);
807 return succs_[0] !=
nullptr;
811 return headHeight_ - 1;
818 return succs_[0] ?
std::min(headHeight_, succs_[0]->
height()) : 0;
821 const value_type&
data()
const {
822 DCHECK(succs_[0] !=
nullptr);
823 return succs_[0]->data();
827 DCHECK(succs_[0] !=
nullptr);
828 return succs_[0]->data();
832 DCHECK(succs_[0] !=
nullptr);
833 return &succs_[0]->data();
843 int layer = curHeight() - 1;
848 int lyr = hints_[layer];
856 preds_[lyr], lyr, data, preds_, succs_);
857 if (foundLayer < 0) {
861 DCHECK(succs_[0] !=
nullptr)
862 <<
"lyr=" << lyr <<
"; max_layer=" << max_layer;
863 return !succs_[0]->markedForRemoval();
868 return accessor_.skiplist()->head_.load(std::memory_order_consume);
873 NodeType *succs_[MAX_HEIGHT], *preds_[MAX_HEIGHT];
iterator lower_bound(const key_type &data) const
void setMarkedForRemoval()
Skipper(const Accessor &accessor)
static SkipListRandomHeight * instance()
std::shared_ptr< SkipListType > slHolder_
SkipListType::const_iterator const_iterator
std::pair< NodeType *, size_t > addOrGetData(U &&data)
size_type max_size() const
static std::shared_ptr< SkipListType > createInstance(int height=1)
size_t getSizeLimit(int height) const
void setSkip(uint8_t h, SkipListNode *next)
csl_iterator(const csl_iterator< OtherVal, OtherNode > &other, typename std::enable_if< std::is_convertible< OtherVal, ValT >::value >::type *=nullptr)
NodeType * lower_bound(const value_type &data) const
const value_type * last() const
Accessor(ConcurrentSkipList *skip_list)
detail::SkipListNode< T > NodeType
static bool less(const value_type &data, const NodeType *node)
SkipListType * skiplist() const
constexpr detail::Map< Move > move
csl_iterator(NodeT *node=nullptr)
auto begin(TestAdlIterable &instance)
static int findInsertionPoint(NodeType *cur, int cur_layer, const value_type &data, NodeType *preds[], NodeType *succs[])
const value_type & data() const
int getHeight(int maxHeight) const
std::pair< NodeType *, int > findNode(const value_type &data) const
static bool greater(const value_type &data, const NodeType *node)
value_type & operator*() const
bool contains(const key_type &data) const
—— Concurrent Priority Queue Implementation ——
void recycle(NodeType *node)
void growHeight(int height)
detail::SkipListNode< T > NodeType
iterator find(const key_type &value)
SkipListType::Skipper Skipper
static std::shared_ptr< SkipListType > createInstance(int height, const NodeAlloc &alloc)
std::pair< NodeType *, int > findNodeRightDown(const value_type &data) const
ConcurrentSkipList(int height)
void init(int *argc, char ***argv, bool removeFlags)
bool equal(const csl_iterator &other) const
const_iterator cend() const
const_iterator cbegin() const
const key_type * last() const
std::atomic< size_t > size_
Contains contains(Needle &&needle)
detail::csl_iterator< const value_type, const NodeType > const_iterator
auto end(TestAdlIterable &instance)
value_type & dereference() const
ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT > SkipListType
constexpr auto data(C &c) -> decltype(c.data())
std::pair< iterator, bool > insert(U &&data)
const T & const_reference
static Accessor create(int height=1)
Skipper(const std::shared_ptr< SkipListType > &skipList)
bool markedForRemoval() const
Accessor & operator=(const Accessor &accessor)
ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT > SkipListType
ptrdiff_t difference_type
static void destroy(NodeAlloc &alloc, SkipListNode *node)
int findInsertionPointGetMaxLayer(const value_type &data, NodeType *preds[], NodeType *succs[], int *max_layer) const
const key_type * first() const
static const char *const value
SkipListNode * copyHead(SkipListNode *node)
ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT > SkipListType
size_t erase(const key_type &data)
std::unique_lock< MicroSpinLock > acquireGuard()
detail::SkipListNode< T > NodeType
size_type count(const key_type &data) const
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn top
static Accessor create(int height, const NodeAlloc &alloc)
Accessor(std::shared_ptr< ConcurrentSkipList > skip_list)
std::pair< NodeType *, int > findNodeDownRight(const value_type &data) const
SkipListType::iterator iterator
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
std::atomic< NodeType * > head_
static SkipListNode * create(NodeAlloc &alloc, int height, U &&data, bool isHead=false)
bool to(const value_type &data)
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
size_t incrementSize(int delta)
ConcurrentSkipList(int height, const NodeAlloc &alloc)
std::unique_lock< folly::MicroSpinLock > ScopedLocker
ptrdiff_t difference_type
const value_type * first() const
value_type * operator->()
const_iterator find(const key_type &value) const
std::pair< key_type *, bool > addOrGetData(const key_type &data)
bool lockNodesForChange(int nodeHeight, ScopedLocker guards[MAX_HEIGHT], NodeType *preds[MAX_HEIGHT], NodeType *succs[MAX_HEIGHT], bool adding=true)
Accessor(const Accessor &accessor)
static bool okToDelete(NodeType *candidate, int layer)
SkipListType::Accessor Accessor
detail::csl_iterator< value_type, NodeType > iterator
NodeType * find(const value_type &data)
SkipListNode * skip(int layer) const
bool add(const key_type &data)