proxygen
folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT > Class Template Reference

#include <ConcurrentSkipList.h>

Classes

class  Accessor
 
class  Skipper
 

Public Types

typedef detail::SkipListNode< TNodeType
 
typedef T value_type
 
typedef T key_type
 
typedef detail::csl_iterator< value_type, NodeTypeiterator
 
typedef detail::csl_iterator< const value_type, const NodeTypeconst_iterator
 

Public Member Functions

 ConcurrentSkipList (int height, const NodeAlloc &alloc)
 
 ConcurrentSkipList (int height)
 
 ~ConcurrentSkipList ()
 

Static Public Member Functions

static Accessor create (int height, const NodeAlloc &alloc)
 
static Accessor create (int height=1)
 
static std::shared_ptr< SkipListTypecreateInstance (int height, const NodeAlloc &alloc)
 
static std::shared_ptr< SkipListTypecreateInstance (int height=1)
 

Private Types

typedef std::unique_lock< folly::MicroSpinLockScopedLocker
 
typedef ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT > SkipListType
 

Private Member Functions

size_t size () const
 
int height () const
 
int maxLayer () const
 
size_t incrementSize (int delta)
 
NodeTypefind (const value_type &data)
 
bool lockNodesForChange (int nodeHeight, ScopedLocker guards[MAX_HEIGHT], NodeType *preds[MAX_HEIGHT], NodeType *succs[MAX_HEIGHT], bool adding=true)
 
template<typename U >
std::pair< NodeType *, size_t > addOrGetData (U &&data)
 
bool remove (const value_type &data)
 
const value_typefirst () const
 
const value_typelast () const
 
int findInsertionPointGetMaxLayer (const value_type &data, NodeType *preds[], NodeType *succs[], int *max_layer) const
 
std::pair< NodeType *, int > findNode (const value_type &data) const
 
std::pair< NodeType *, int > findNodeDownRight (const value_type &data) const
 
std::pair< NodeType *, int > findNodeRightDown (const value_type &data) const
 
NodeTypelower_bound (const value_type &data) const
 
void growHeight (int height)
 
void recycle (NodeType *node)
 

Static Private Member Functions

static bool greater (const value_type &data, const NodeType *node)
 
static bool less (const value_type &data, const NodeType *node)
 
static int findInsertionPoint (NodeType *cur, int cur_layer, const value_type &data, NodeType *preds[], NodeType *succs[])
 
static bool okToDelete (NodeType *candidate, int layer)
 

Private Attributes

detail::NodeRecycler< NodeType, NodeAlloc > recycler_
 
std::atomic< NodeType * > head_
 
std::atomic< size_t > size_
 

Detailed Description

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
class folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >

Definition at line 145 of file ConcurrentSkipList.h.

Member Typedef Documentation

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef detail::csl_iterator<const value_type, const NodeType> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::const_iterator

Definition at line 161 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef detail::csl_iterator<value_type, NodeType> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::iterator

Definition at line 160 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef T folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::key_type

Definition at line 158 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef detail::SkipListNode<T> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::NodeType

Definition at line 156 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef std::unique_lock<folly::MicroSpinLock> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::ScopedLocker
private

Definition at line 151 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef ConcurrentSkipList<T, Comp, NodeAlloc, MAX_HEIGHT> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::SkipListType
private

Definition at line 153 of file ConcurrentSkipList.h.

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
typedef T folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::value_type

Definition at line 157 of file ConcurrentSkipList.h.

Constructor & Destructor Documentation

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::ConcurrentSkipList ( int  height,
const NodeAlloc &  alloc 
)
inlineexplicit

Definition at line 166 of file ConcurrentSkipList.h.

167  : recycler_(alloc),
168  head_(NodeType::create(recycler_.alloc(), height, value_type(), true)),
169  size_(0) {}
std::atomic< size_t > size_
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
std::atomic< NodeType * > head_
static SkipListNode * create(NodeAlloc &alloc, int height, U &&data, bool isHead=false)
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::ConcurrentSkipList ( int  height)
inlineexplicit

Definition at line 171 of file ConcurrentSkipList.h.

172  : recycler_(),
173  head_(NodeType::create(recycler_.alloc(), height, value_type(), true)),
174  size_(0) {}
std::atomic< size_t > size_
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
std::atomic< NodeType * > head_
static SkipListNode * create(NodeAlloc &alloc, int height, U &&data, bool isHead=false)
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::~ConcurrentSkipList ( )
inline

Definition at line 201 of file ConcurrentSkipList.h.

References current, folly::detail::SkipListNode< T >::destroy(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycler_, and value.

201  {
202  if /* constexpr */ (NodeType::template DestroyIsNoOp<NodeAlloc>::value) {
203  // Avoid traversing the list if using arena allocator.
204  return;
205  }
206  for (NodeType* current = head_.load(std::memory_order_relaxed); current;) {
207  NodeType* tmp = current->skip(0);
209  current = tmp;
210  }
211  }
detail::SkipListNode< T > NodeType
int current
static void destroy(NodeAlloc &alloc, SkipListNode *node)
static const char *const value
Definition: Conv.cpp:50
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
std::atomic< NodeType * > head_

Member Function Documentation

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
template<typename U >
std::pair<NodeType*, size_t> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::addOrGetData ( U &&  data)
inlineprivate

Definition at line 314 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::create(), folly::data(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPointGetMaxLayer(), folly::detail::SkipListNode< T >::fullyLinked(), folly::detail::SkipListRandomHeight::getHeight(), folly::detail::SkipListRandomHeight::getSizeLimit(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::growHeight(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::incrementSize(), folly::detail::SkipListRandomHeight::instance(), k, folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::lockNodesForChange(), folly::detail::SkipListNode< T >::markedForRemoval(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycler_, folly::detail::SkipListNode< T >::setFullyLinked(), folly::detail::SkipListNode< T >::setSkip(), and UNLIKELY.

314  {
315  NodeType *preds[MAX_HEIGHT], *succs[MAX_HEIGHT];
316  NodeType* newNode;
317  size_t newSize;
318  while (true) {
319  int max_layer = 0;
320  int layer = findInsertionPointGetMaxLayer(data, preds, succs, &max_layer);
321 
322  if (layer >= 0) {
323  NodeType* nodeFound = succs[layer];
324  DCHECK(nodeFound != nullptr);
325  if (nodeFound->markedForRemoval()) {
326  continue; // if it's getting deleted retry finding node.
327  }
328  // wait until fully linked.
329  while (UNLIKELY(!nodeFound->fullyLinked())) {
330  }
331  return std::make_pair(nodeFound, 0);
332  }
333 
334  // need to capped at the original height -- the real height may have grown
335  int nodeHeight =
337 
338  ScopedLocker guards[MAX_HEIGHT];
339  if (!lockNodesForChange(nodeHeight, guards, preds, succs)) {
340  continue; // give up the locks and retry until all valid
341  }
342 
343  // locks acquired and all valid, need to modify the links under the locks.
344  newNode = NodeType::create(
345  recycler_.alloc(), nodeHeight, std::forward<U>(data));
346  for (int k = 0; k < nodeHeight; ++k) {
347  newNode->setSkip(k, succs[k]);
348  preds[k]->setSkip(k, newNode);
349  }
350 
351  newNode->setFullyLinked();
352  newSize = incrementSize(1);
353  break;
354  }
355 
356  int hgt = height();
357  size_t sizeLimit =
359 
360  if (hgt < MAX_HEIGHT && newSize > sizeLimit) {
361  growHeight(hgt + 1);
362  }
363  CHECK_GT(newSize, 0);
364  return std::make_pair(newNode, newSize);
365  }
static SkipListRandomHeight * instance()
detail::SkipListNode< T > NodeType
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
int findInsertionPointGetMaxLayer(const value_type &data, NodeType *preds[], NodeType *succs[], int *max_layer) const
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
static SkipListNode * create(NodeAlloc &alloc, int height, U &&data, bool isHead=false)
size_t incrementSize(int delta)
std::unique_lock< folly::MicroSpinLock > ScopedLocker
#define UNLIKELY(x)
Definition: Likely.h:48
bool lockNodesForChange(int nodeHeight, ScopedLocker guards[MAX_HEIGHT], NodeType *preds[MAX_HEIGHT], NodeType *succs[MAX_HEIGHT], bool adding=true)
KeyT k
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static Accessor folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::create ( int  height,
const NodeAlloc &  alloc 
)
inlinestatic

Definition at line 177 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::createInstance().

177  {
178  return Accessor(createInstance(height, alloc));
179  }
static std::shared_ptr< SkipListType > createInstance(int height, const NodeAlloc &alloc)
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static Accessor folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::create ( int  height = 1)
inlinestatic

Definition at line 181 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::createInstance(), and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height().

181  {
182  return Accessor(createInstance(height));
183  }
static std::shared_ptr< SkipListType > createInstance(int height, const NodeAlloc &alloc)
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static std::shared_ptr<SkipListType> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::createInstance ( int  height,
const NodeAlloc &  alloc 
)
inlinestatic

Definition at line 186 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::create().

188  {
189  return std::make_shared<ConcurrentSkipList>(height, alloc);
190  }
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static std::shared_ptr<SkipListType> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::createInstance ( int  height = 1)
inlinestatic

Definition at line 192 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height().

192  {
193  return std::make_shared<ConcurrentSkipList>(height);
194  }
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
NodeType* folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::find ( const value_type data)
inlineprivate

Definition at line 268 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNode().

268  {
269  auto ret = findNode(data);
270  if (ret.second && !ret.first->markedForRemoval()) {
271  return ret.first;
272  }
273  return nullptr;
274  }
std::pair< NodeType *, int > findNode(const value_type &data) const
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static int folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPoint ( NodeType cur,
int  cur_layer,
const value_type data,
NodeType preds[],
NodeType succs[] 
)
inlinestaticprivate

Definition at line 222 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::greater(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::less(), and folly::detail::SkipListNode< T >::skip().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPointGetMaxLayer(), and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::Skipper::to().

227  {
228  int foundLayer = -1;
229  NodeType* pred = cur;
230  NodeType* foundNode = nullptr;
231  for (int layer = cur_layer; layer >= 0; --layer) {
232  NodeType* node = pred->skip(layer);
233  while (greater(data, node)) {
234  pred = node;
235  node = node->skip(layer);
236  }
237  if (foundLayer == -1 && !less(data, node)) { // the two keys equal
238  foundLayer = layer;
239  foundNode = node;
240  }
241  preds[layer] = pred;
242 
243  // if found, succs[0..foundLayer] need to point to the cached foundNode,
244  // as foundNode might be deleted at the same time thus pred->skip() can
245  // return nullptr or another node.
246  succs[layer] = foundNode ? foundNode : node;
247  }
248  return foundLayer;
249  }
detail::SkipListNode< T > NodeType
static bool less(const value_type &data, const NodeType *node)
static bool greater(const value_type &data, const NodeType *node)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
int folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPointGetMaxLayer ( const value_type data,
NodeType preds[],
NodeType succs[],
int *  max_layer 
) const
inlineprivate

Definition at line 436 of file ConcurrentSkipList.h.

References folly::data(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPoint(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::maxLayer().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::addOrGetData(), and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::remove().

440  {
441  *max_layer = maxLayer();
442  return findInsertionPoint(
443  head_.load(std::memory_order_consume), *max_layer, data, preds, succs);
444  }
static int findInsertionPoint(NodeType *cur, int cur_layer, const value_type &data, NodeType *preds[], NodeType *succs[])
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
std::atomic< NodeType * > head_
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
std::pair<NodeType*, int> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNode ( const value_type data) const
inlineprivate

Definition at line 451 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNodeDownRight().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::find(), and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::lower_bound().

451  {
452  return findNodeDownRight(data);
453  }
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
std::pair< NodeType *, int > findNodeDownRight(const value_type &data) const
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
std::pair<NodeType*, int> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNodeDownRight ( const value_type data) const
inlineprivate

Definition at line 458 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::greater(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, folly::detail::SkipListNode< T >::height(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::less(), and folly::detail::SkipListNode< T >::skip().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNode().

458  {
459  NodeType* pred = head_.load(std::memory_order_consume);
460  int ht = pred->height();
461  NodeType* node = nullptr;
462 
463  bool found = false;
464  while (!found) {
465  // stepping down
466  for (; ht > 0 && less(data, node = pred->skip(ht - 1)); --ht) {
467  }
468  if (ht == 0) {
469  return std::make_pair(node, 0); // not found
470  }
471  // node <= data now, but we need to fix up ht
472  --ht;
473 
474  // stepping right
475  while (greater(data, node)) {
476  pred = node;
477  node = node->skip(ht);
478  }
479  found = !less(data, node);
480  }
481  return std::make_pair(node, found);
482  }
detail::SkipListNode< T > NodeType
static bool less(const value_type &data, const NodeType *node)
static bool greater(const value_type &data, const NodeType *node)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
std::atomic< NodeType * > head_
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
std::pair<NodeType*, int> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNodeRightDown ( const value_type data) const
inlineprivate

Definition at line 486 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::greater(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::less(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::maxLayer(), folly::detail::SkipListNode< T >::skip(), and folly::pushmi::top.

486  {
487  NodeType* pred = head_.load(std::memory_order_consume);
488  NodeType* node = nullptr;
489  auto top = maxLayer();
490  int found = 0;
491  for (int layer = top; !found && layer >= 0; --layer) {
492  node = pred->skip(layer);
493  while (greater(data, node)) {
494  pred = node;
495  node = node->skip(layer);
496  }
497  found = !less(data, node);
498  }
499  return std::make_pair(node, found);
500  }
detail::SkipListNode< T > NodeType
static bool less(const value_type &data, const NodeType *node)
static bool greater(const value_type &data, const NodeType *node)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn top
std::atomic< NodeType * > head_
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
const value_type* folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::first ( ) const
inlineprivate

Definition at line 409 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_.

409  {
410  auto node = head_.load(std::memory_order_consume)->skip(0);
411  return node ? &node->data() : nullptr;
412  }
std::atomic< NodeType * > head_
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static bool folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::greater ( const value_type data,
const NodeType node 
)
inlinestaticprivate
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
void folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::growHeight ( int  height)
inlineprivate

Definition at line 510 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::acquireGuard(), folly::detail::SkipListNode< T >::copyHead(), folly::detail::SkipListNode< T >::create(), folly::detail::SkipListNode< T >::destroy(), g(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, folly::detail::SkipListNode< T >::height(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycle(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycler_, and folly::detail::SkipListNode< T >::setMarkedForRemoval().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::addOrGetData().

510  {
511  NodeType* oldHead = head_.load(std::memory_order_consume);
512  if (oldHead->height() >= height) { // someone else already did this
513  return;
514  }
515 
516  NodeType* newHead =
517  NodeType::create(recycler_.alloc(), height, value_type(), true);
518 
519  { // need to guard the head node in case others are adding/removing
520  // nodes linked to the head.
521  ScopedLocker g = oldHead->acquireGuard();
522  newHead->copyHead(oldHead);
523  NodeType* expected = oldHead;
524  if (!head_.compare_exchange_strong(
525  expected, newHead, std::memory_order_release)) {
526  // if someone has already done the swap, just return.
527  NodeType::destroy(recycler_.alloc(), newHead);
528  return;
529  }
530  oldHead->setMarkedForRemoval();
531  }
532  recycle(oldHead);
533  }
detail::SkipListNode< T > NodeType
void recycle(NodeType *node)
static void destroy(NodeAlloc &alloc, SkipListNode *node)
g_t g(f_t)
detail::NodeRecycler< NodeType, NodeAlloc > recycler_
std::atomic< NodeType * > head_
static SkipListNode * create(NodeAlloc &alloc, int height, U &&data, bool isHead=false)
std::unique_lock< folly::MicroSpinLock > ScopedLocker
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
size_t folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::incrementSize ( int  delta)
inlineprivate
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
const value_type* folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::last ( ) const
inlineprivate

Definition at line 414 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::data(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::head_, folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::maxLayer(), and folly::detail::SkipListNode< T >::skip().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::Accessor::pop_back().

414  {
415  NodeType* pred = head_.load(std::memory_order_consume);
416  NodeType* node = nullptr;
417  for (int layer = maxLayer(); layer >= 0; --layer) {
418  do {
419  node = pred->skip(layer);
420  if (node) {
421  pred = node;
422  }
423  } while (node != nullptr);
424  }
425  return pred == head_.load(std::memory_order_relaxed) ? nullptr
426  : &pred->data();
427  }
detail::SkipListNode< T > NodeType
std::atomic< NodeType * > head_
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static bool folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::less ( const value_type data,
const NodeType node 
)
inlinestaticprivate
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
bool folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::lockNodesForChange ( int  nodeHeight,
ScopedLocker  guards[MAX_HEIGHT],
NodeType preds[MAX_HEIGHT],
NodeType succs[MAX_HEIGHT],
bool  adding = true 
)
inlineprivate

Definition at line 279 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::acquireGuard(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::height(), folly::detail::SkipListNode< T >::markedForRemoval(), and folly::detail::SkipListNode< T >::skip().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::addOrGetData(), and folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::remove().

284  {
285  NodeType *pred, *succ, *prevPred = nullptr;
286  bool valid = true;
287  for (int layer = 0; valid && layer < nodeHeight; ++layer) {
288  pred = preds[layer];
289  DCHECK(pred != nullptr) << "layer=" << layer << " height=" << height()
290  << " nodeheight=" << nodeHeight;
291  succ = succs[layer];
292  if (pred != prevPred) {
293  guards[layer] = pred->acquireGuard();
294  prevPred = pred;
295  }
296  valid = !pred->markedForRemoval() &&
297  pred->skip(layer) == succ; // check again after locking
298 
299  if (adding) { // when adding a node, the succ shouldn't be going away
300  valid = valid && (succ == nullptr || !succ->markedForRemoval());
301  }
302  }
303 
304  return valid;
305  }
detail::SkipListNode< T > NodeType
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
NodeType* folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::lower_bound ( const value_type data) const
inlineprivate

Definition at line 502 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findNode().

502  {
503  auto node = findNode(data).first;
504  while (node != nullptr && node->markedForRemoval()) {
505  node = node->skip(0);
506  }
507  return node;
508  }
std::pair< NodeType *, int > findNode(const value_type &data) const
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
static bool folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::okToDelete ( NodeType candidate,
int  layer 
)
inlinestaticprivate

Definition at line 429 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::fullyLinked(), folly::detail::SkipListNode< T >::markedForRemoval(), and folly::detail::SkipListNode< T >::maxLayer().

Referenced by folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::remove().

429  {
430  DCHECK(candidate != nullptr);
431  return candidate->fullyLinked() && candidate->maxLayer() == layer &&
432  !candidate->markedForRemoval();
433  }
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
void folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycle ( NodeType node)
inlineprivate
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
bool folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::remove ( const value_type data)
inlineprivate

Definition at line 367 of file ConcurrentSkipList.h.

References folly::detail::SkipListNode< T >::acquireGuard(), folly::data(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::findInsertionPointGetMaxLayer(), folly::detail::SkipListNode< T >::height(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::incrementSize(), k, folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::lockNodesForChange(), folly::detail::SkipListNode< T >::markedForRemoval(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::okToDelete(), folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::recycle(), folly::detail::SkipListNode< T >::setMarkedForRemoval(), folly::detail::SkipListNode< T >::setSkip(), and folly::detail::SkipListNode< T >::skip().

367  {
368  NodeType* nodeToDelete = nullptr;
369  ScopedLocker nodeGuard;
370  bool isMarked = false;
371  int nodeHeight = 0;
372  NodeType *preds[MAX_HEIGHT], *succs[MAX_HEIGHT];
373 
374  while (true) {
375  int max_layer = 0;
376  int layer = findInsertionPointGetMaxLayer(data, preds, succs, &max_layer);
377  if (!isMarked && (layer < 0 || !okToDelete(succs[layer], layer))) {
378  return false;
379  }
380 
381  if (!isMarked) {
382  nodeToDelete = succs[layer];
383  nodeHeight = nodeToDelete->height();
384  nodeGuard = nodeToDelete->acquireGuard();
385  if (nodeToDelete->markedForRemoval()) {
386  return false;
387  }
388  nodeToDelete->setMarkedForRemoval();
389  isMarked = true;
390  }
391 
392  // acquire pred locks from bottom layer up
393  ScopedLocker guards[MAX_HEIGHT];
394  if (!lockNodesForChange(nodeHeight, guards, preds, succs, false)) {
395  continue; // this will unlock all the locks
396  }
397 
398  for (int k = nodeHeight - 1; k >= 0; --k) {
399  preds[k]->setSkip(k, nodeToDelete->skip(k));
400  }
401 
402  incrementSize(-1);
403  break;
404  }
405  recycle(nodeToDelete);
406  return true;
407  }
detail::SkipListNode< T > NodeType
void recycle(NodeType *node)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
int findInsertionPointGetMaxLayer(const value_type &data, NodeType *preds[], NodeType *succs[], int *max_layer) const
size_t incrementSize(int delta)
std::unique_lock< folly::MicroSpinLock > ScopedLocker
bool lockNodesForChange(int nodeHeight, ScopedLocker guards[MAX_HEIGHT], NodeType *preds[MAX_HEIGHT], NodeType *succs[MAX_HEIGHT], bool adding=true)
KeyT k
static bool okToDelete(NodeType *candidate, int layer)
template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
size_t folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::size ( ) const
inlineprivate

Definition at line 251 of file ConcurrentSkipList.h.

References folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::size_.

251  {
252  return size_.load(std::memory_order_relaxed);
253  }
std::atomic< size_t > size_

Member Data Documentation

template<typename T, typename Comp = std::less<T>, typename NodeAlloc = SysAllocator<void>, int MAX_HEIGHT = 24>
std::atomic<size_t> folly::ConcurrentSkipList< T, Comp, NodeAlloc, MAX_HEIGHT >::size_
private

The documentation for this class was generated from the following file: