X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2FConcurrentSkipList-inl.h;h=881d05350bb31b77794c5d097a423d20e1687502;hb=b2ae6ce3b6fc237e85cc988ad4a47a8453250b88;hp=e4144bcbfb57dfaa035ace57a2f163ac62f4dbcf;hpb=dee8a5180aa542d98d1b71c74f83a006e4627952;p=folly.git diff --git a/folly/ConcurrentSkipList-inl.h b/folly/ConcurrentSkipList-inl.h index e4144bcb..881d0535 100644 --- a/folly/ConcurrentSkipList-inl.h +++ b/folly/ConcurrentSkipList-inl.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ #include #include #include + #include #include #include @@ -37,20 +38,24 @@ namespace folly { namespace detail { -template class csl_iterator; +template class csl_iterator; -template +template class SkipListNode : private boost::noncopyable { - enum { + enum : uint16_t { IS_HEAD_NODE = 1, MARKED_FOR_REMOVAL = (1 << 1), FULLY_LINKED = (1 << 2), }; + public: typedef T value_type; - template::value>::type> + template < + typename NodeAlloc, + typename U, + typename = + typename std::enable_if::value>::type> static SkipListNode* create( NodeAlloc& alloc, int height, U&& data, bool isHead = false) { DCHECK(height >= 1 && height < 64) << height; @@ -59,27 +64,26 @@ class SkipListNode : private boost::noncopyable { height * sizeof(std::atomic); auto* node = static_cast(alloc.allocate(size)); // do placement new - new (node) SkipListNode(height, std::forward(data), isHead); + new (node) SkipListNode(uint8_t(height), std::forward(data), isHead); return node; } - template + template static void destroy(NodeAlloc& alloc, SkipListNode* node) { node->~SkipListNode(); alloc.deallocate(node); } - template - static constexpr bool destroyIsNoOp() { - return IsArenaAllocator::value && - boost::has_trivial_destructor::value; - } + template + struct DestroyIsNoOp : std::integral_constant::value && + boost::has_trivial_destructor::value> { }; // copy the head node to a new head node assuming lock acquired SkipListNode* copyHead(SkipListNode* node) { DCHECK(node != nullptr && height_ > node->height_); setFlags(node->getFlags()); - for (int i = 0; i < node->height_; ++i) { + for (uint8_t i = 0; i < node->height_; ++i) { setSkip(i, node->skip(i)); } return this; @@ -118,23 +122,25 @@ class SkipListNode : private boost::noncopyable { bool isHeadNode() const { return getFlags() & IS_HEAD_NODE; } void setIsHeadNode() { - setFlags(getFlags() | IS_HEAD_NODE); + setFlags(uint16_t(getFlags() | IS_HEAD_NODE)); } void setFullyLinked() { - setFlags(getFlags() | FULLY_LINKED); + setFlags(uint16_t(getFlags() | FULLY_LINKED)); } void setMarkedForRemoval() { - setFlags(getFlags() | MARKED_FOR_REMOVAL); + setFlags(uint16_t(getFlags() | MARKED_FOR_REMOVAL)); } private: // Note! this can only be called from create() as a placement new. - template + template SkipListNode(uint8_t height, U&& data, bool isHead) : height_(height), data_(std::forward(data)) { spinLock_.init(); setFlags(0); - if (isHead) setIsHeadNode(); + if (isHead) { + setIsHeadNode(); + } // need to explicitly init the dynamic atomic pointer array for (uint8_t i = 0; i < height_; ++i) { new (&skip_[i]) std::atomic(nullptr); @@ -225,12 +231,12 @@ class SkipListRandomHeight { size_t sizeLimitTable_[kMaxHeight]; }; -template +template class NodeRecycler; -template +template class NodeRecycler()>::type> { + !NodeType::template DestroyIsNoOp::value>::type> { public: explicit NodeRecycler(const NodeAlloc& alloc) : refs_(0), dirty_(false), alloc_(alloc) { lock_.init(); } @@ -249,7 +255,7 @@ class NodeRecycler g(lock_); if (nodes_.get() == nullptr) { - nodes_.reset(new std::vector(1, node)); + nodes_ = std::make_unique>(1, node); } else { nodes_->push_back(node); } @@ -314,9 +320,9 @@ class NodeRecycler +template class NodeRecycler()>::type> { + NodeType::template DestroyIsNoOp::value>::type> { public: explicit NodeRecycler(const NodeAlloc& alloc) : alloc_(alloc) { } @@ -331,4 +337,5 @@ class NodeRecycler