Commit 0fd4f579 authored by Philip Pronin's avatar Philip Pronin Committed by ptarjan

make ConcurrentSkipList ctor public

Summary:
There is no reason to force heap allocation for
`ConcurrentSkipList`.

Test Plan: fbconfig -r unicorn/test && fbmake opt -j32

@override-unit-failures

Reviewed By: lucian@fb.com

FB internal diff: D1261183
parent ff03c3a8
...@@ -121,17 +121,15 @@ Sample usage: ...@@ -121,17 +121,15 @@ Sample usage:
#define FOLLY_CONCURRENT_SKIP_LIST_H_ #define FOLLY_CONCURRENT_SKIP_LIST_H_
#include <algorithm> #include <algorithm>
#include <atomic>
#include <climits> #include <climits>
#include <memory>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <atomic>
#include <thread>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/scoped_ptr.hpp>
#include <memory>
#include <glog/logging.h> #include <glog/logging.h>
#include "folly/ConcurrentSkipList-inl.h" #include "folly/ConcurrentSkipList-inl.h"
#include "folly/Likely.h" #include "folly/Likely.h"
#include "folly/SmallLocks.h" #include "folly/SmallLocks.h"
...@@ -153,29 +151,25 @@ class ConcurrentSkipList { ...@@ -153,29 +151,25 @@ class ConcurrentSkipList {
typedef T value_type; typedef T value_type;
typedef T key_type; typedef T key_type;
typedef detail::csl_iterator<value_type, NodeType> iterator; typedef detail::csl_iterator<value_type, NodeType> iterator;
typedef detail::csl_iterator<const value_type, const NodeType> const_iterator; typedef detail::csl_iterator<const value_type, const NodeType> const_iterator;
class Accessor; class Accessor;
class Skipper; class Skipper;
// convenient function to get an Accessor to a new instance. explicit ConcurrentSkipList(int height)
static Accessor create(int height=1) { : head_(NodeType::create(height, value_type(), true)), size_(0) { }
return Accessor(createInstance(height));
}
// create a shared_ptr skiplist object with initial head height. // Convenient function to get an Accessor to a new instance.
static std::shared_ptr<SkipListType> createInstance(int height=1) { static Accessor create(int height = 1) {
return std::shared_ptr<SkipListType>(new SkipListType(height)); return Accessor(createInstance(height));
} }
// create a unique_ptr skiplist object with initial head height. // Create a shared_ptr skiplist object with initial head height.
static std::unique_ptr<SkipListType> createRawInstance(int height=1) { static std::shared_ptr<SkipListType> createInstance(int height = 1) {
return std::unique_ptr<SkipListType>(new SkipListType(height)); return std::make_shared<ConcurrentSkipList>(height);
} }
//=================================================================== //===================================================================
// Below are implementation details. // Below are implementation details.
// Please see ConcurrentSkipList::Accessor for stdlib-like APIs. // Please see ConcurrentSkipList::Accessor for stdlib-like APIs.
...@@ -183,15 +177,14 @@ class ConcurrentSkipList { ...@@ -183,15 +177,14 @@ class ConcurrentSkipList {
~ConcurrentSkipList() { ~ConcurrentSkipList() {
CHECK_EQ(recycler_.refs(), 0); CHECK_EQ(recycler_.refs(), 0);
while (NodeType* current = head_.load(std::memory_order_relaxed)) { for (NodeType* current = head_.load(std::memory_order_relaxed); current; ) {
NodeType* tmp = current->skip(0); NodeType* tmp = current->skip(0);
NodeType::destroy(current); NodeType::destroy(current);
head_.store(tmp, std::memory_order_relaxed); current = tmp;
} }
} }
private: private:
static bool greater(const value_type &data, const NodeType *node) { static bool greater(const value_type &data, const NodeType *node) {
return node && Comp()(node->data(), data); return node && Comp()(node->data(), data);
} }
...@@ -267,7 +260,7 @@ class ConcurrentSkipList { ...@@ -267,7 +260,7 @@ class ConcurrentSkipList {
return refs_.fetch_add(-1, std::memory_order_relaxed); return refs_.fetch_add(-1, std::memory_order_relaxed);
} }
boost::scoped_ptr<std::vector<NodeType*> > newNodes; std::unique_ptr<std::vector<NodeType*>> newNodes;
{ {
std::lock_guard<MicroSpinLock> g(lock_); std::lock_guard<MicroSpinLock> g(lock_);
if (nodes_.get() == nullptr || refs() > 1) { if (nodes_.get() == nullptr || refs() > 1) {
...@@ -294,15 +287,12 @@ class ConcurrentSkipList { ...@@ -294,15 +287,12 @@ class ConcurrentSkipList {
} }
private: private:
boost::scoped_ptr<std::vector<NodeType*>> nodes_; std::unique_ptr<std::vector<NodeType*>> nodes_;
std::atomic<int32_t> refs_; // current number of visitors to the list std::atomic<int32_t> refs_; // current number of visitors to the list
std::atomic<bool> dirty_; // whether *nodes_ is non-empty std::atomic<bool> dirty_; // whether *nodes_ is non-empty
MicroSpinLock lock_; // protects access to *nodes_ MicroSpinLock lock_; // protects access to *nodes_
}; // class ConcurrentSkipList::Recycler }; // class ConcurrentSkipList::Recycler
explicit ConcurrentSkipList(int height) :
head_(NodeType::create(height, value_type(), true)), size_(0) {}
size_t size() const { return size_.load(std::memory_order_relaxed); } size_t size() const { return size_.load(std::memory_order_relaxed); }
int height() const { int height() const {
return head_.load(std::memory_order_consume)->height(); return head_.load(std::memory_order_consume)->height();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment