17 auto &&
getId(
const T &e)
const {
return e.getId(); }
38template <
typename T,
typename Adapter = PassthroughAdapter<T>>
46 typename std::remove_reference<decltype(std::declval<Adapter &>().getId(
47 std::declval<T &>()))>::type;
54 std::atomic<RadixElement>
root;
81 root.load().decrementRefCount();
100 rhs.root =
root.load();
129 if (leaf ==
nullptr ||
getId(*leaf) != key) {
139 T
const *ptr =
const_cast<RadixTree *
>(
this)->
get(key).release();
143 template <
typename Callable>
bool forEachLeaf(Callable &&func)
const {
148#define SEEK_LEAF_LOOP() \
149 RadixElement e = eptr->load(); \
153 while (e.isNode()) { \
155 auto nptr = e.getNode(); \
156 if (!nptr->isShared()) { \
157 eptr = nptr->get(level--, key); \
162 auto copy = std::make_unique<RadixNode>(*nptr); \
163 if (!eptr->compare_exchange_strong(e, RadixElement(copy.get()))) { \
169 e.decrementRefCount(); \
170 eptr = copy->get(level--, key); \
184 std::atomic<RadixElement> *eptr = &
root;
188 T *leaf = e.getLeaf();
189 if (leaf ==
nullptr ||
getId(*leaf) != key) {
215 std::atomic<RadixElement> *eptr = &
root;
221 if (e.getLeaf() ==
nullptr) {
222 if (eptr->compare_exchange_strong(e,
236 if (key == leafKey) {
242 auto newChild = std::make_unique<RadixNode>(level, leafKey, e);
243 if (eptr->compare_exchange_strong(e,
256 template <
typename Callable>
260 if (leaf !=
nullptr) {
268 [&](
const std::atomic<RadixElement> *pElement) {
335 return reinterpret_cast<T *
>(
raw & ~DISCRIMINANT);
350 std::array<RadixElement, CHILD_PER_LEVEL>
357 get(level, key)->store(e);
362 e.decrementRefCount();
369 e.incrementRefCount();
376 std::atomic<RadixElement> *
get(uint32_t level,
const KeyType &key) {
382 template <
typename Callable>
bool forEachChild(Callable &&func)
const {
393 static_assert(
alignof(T) > 1,
"T's alignment must be 2 or more.");
394 static_assert(
alignof(RadixNode) > 1,
395 "RadixNode alignment must be 2 or more.");
static void synchronize()
T * get()
Get allows to access the undelying pointer.
static RCUPtr acquire(T *&ptrIn)
Acquire ownership of some pointer.
T * release()
Release transfers ownership of the pointer from RCUPtr to the caller.
static RCUPtr copy(T *ptr)
Construct a new RCUPtr without transferring owership.
auto && getId(const T &e) const
bool getDiscriminant() const
bool isNode() const
Node features.
static const uintptr_t DISCRIMINANT
const T * getLeaf() const
bool isLeaf() const
Leaf features.
RadixElement(RadixNode *nodeIn) noexcept
void incrementRefCount()
RadixElement is designed to be a dumb wrapper.
const RadixNode * getNode() const
RadixElement(T *leafIn) noexcept
bool forEachChild(Callable &&func) const
RadixNode & operator=(const RadixNode &)=delete
std::atomic< RadixElement > * get(uint32_t level, const KeyType &key)
RadixNode(uint32_t level, const KeyType &key, RadixElement e)
std::array< RadixElement, CHILD_PER_LEVEL > non_atomic_children_DO_NOT_USE
RadixNode(const RadixNode &rhs)
std::array< std::atomic< RadixElement >, CHILD_PER_LEVEL > children
IMPLEMENT_RCU_REFCOUNT(uint64_t)
This is a radix tree storing values identified by a unique key.
static const uint32_t TOP_LEVEL
RCUPtr< T > remove(const KeyType &key)
Remove an element from the tree.
KeyType getId(const T &value) const
static const size_t CHILD_PER_LEVEL
RadixTree(RadixTree &&src)
Move semantic.
typename std::remove_reference< decltype(std::declval< Adapter & >().getId(std::declval< T & >()))>::type KeyType
bool forEachLeaf(RadixElement e, Callable &&func) const
RadixTree & operator=(const RadixTree &rhs)
static const size_t KEY_BITS
std::atomic< RadixElement > root
RadixTree(const RadixTree &src)
Copy semantic.
RCUPtr< const T > get(const KeyType &key) const
bool insert(const KeyType &key, RCUPtr< T > value)
RCUPtr< T > get(const KeyType &key)
Get the value corresponding to a key.
RadixTree & operator=(RadixTree &&rhs)
bool forEachLeaf(Callable &&func) const
bool insert(const RCUPtr< T > &value)
Insert a value into the tree.