提交 2ca11e63 创建 作者: David Benjamin's avatar David Benjamin

Have descend return the radix level we stopped at

Rather awkward API, but it's enough to implement skipping of empty nodes.
上级 e10e8bda
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#include "cpputil.hh" #include "cpputil.hh"
#include "radix.hh" #include "radix.hh"
// Returns the level we stopped at.
template<class CB> template<class CB>
void u32
descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create) descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create)
{ {
static_assert(key_bits == bits_per_level * radix_levels, static_assert(key_bits == bits_per_level * radix_levels,
...@@ -14,26 +15,29 @@ descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create) ...@@ -14,26 +15,29 @@ descend(u64 key, markptr<void> *n, u32 level, CB cb, bool create)
assert(n); assert(n);
void *v = n->ptr(); void *v = n->ptr();
if (v == 0) { if (v == 0 && create) {
// Node isn't there. Just return.
if (!create)
return;
radix_node *new_rn = new radix_node(); radix_node *new_rn = new radix_node();
if (n->ptr().cmpxch_update(&v, (void*) new_rn)) if (n->ptr().cmpxch_update(&v, (void*) new_rn))
v = new_rn; v = new_rn;
else else
delete new_rn; delete new_rn;
} }
// Node isn't there. Just return.
if (v == 0) {
return level+1;
}
radix_node *rn = (radix_node*) v; radix_node *rn = (radix_node*) v;
u64 idx = key >> (bits_per_level * level); u64 idx = key >> (bits_per_level * level);
idx &= (1<<bits_per_level)-1; idx &= (1<<bits_per_level)-1;
markptr<void> *vptr = &rn->ptr[idx]; markptr<void> *vptr = &rn->ptr[idx];
if (level == 0) if (level == 0) {
cb(vptr); cb(vptr);
else return level;
descend(key, vptr, level-1, cb, create); } else {
return descend(key, vptr, level-1, cb, create);
}
} }
radix_elem* radix_elem*
...@@ -55,11 +59,14 @@ radix::search_lock(u64 start, u64 size) ...@@ -55,11 +59,14 @@ radix::search_lock(u64 start, u64 size)
radix_range::radix_range(radix *r, u64 start, u64 size) radix_range::radix_range(radix *r, u64 start, u64 size)
: r_(r), start_(start), size_(size) : r_(r), start_(start), size_(size)
{ {
for (u64 k = start_; k != start_ + size_; k++) for (u64 k = start_; k != start_ + size_; k++) {
descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
while (!v->mark().xchg(true)) while (!v->mark().xchg(true))
; // spin ; // spin
}, true); }, true) != 0) {
panic("radix_range");
}
}
} }
radix_range::~radix_range() radix_range::~radix_range()
...@@ -67,10 +74,13 @@ radix_range::~radix_range() ...@@ -67,10 +74,13 @@ radix_range::~radix_range()
if (!r_) if (!r_)
return; return;
for (u64 k = start_; k != start_ + size_; k++) for (u64 k = start_; k != start_ + size_; k++) {
descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [](markptr<void> *v) {
v->mark() = false; v->mark() = false;
}, true); }, true) != 0) {
panic("~radix_range");
}
}
} }
void void
...@@ -82,15 +92,18 @@ radix_range::replace(u64 start, u64 size, radix_elem *val) ...@@ -82,15 +92,18 @@ radix_range::replace(u64 start, u64 size, radix_elem *val)
assert(start >= start_); assert(start >= start_);
assert(start + size <= start_ + size_); assert(start + size <= start_ + size_);
for (u64 k = start; k != start + size; k++) for (u64 k = start; k != start + size; k++) {
descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) { if (descend(k, &r_->root_, radix_levels-1, [val](markptr<void> *v) {
void* cur = v->ptr().load(); void* cur = v->ptr().load();
while (!v->ptr().cmpxch_update(&cur, val)) while (!v->ptr().cmpxch_update(&cur, val))
; // spin ; // spin
val->incref(); val->incref();
if (cur) if (cur)
((radix_elem*) cur)->decref(); ((radix_elem*) cur)->decref();
}, true); }, true)) {
panic("radix_range::replace");
}
}
} }
radix_elem* radix_elem*
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论