Remove dontInvalidate arg from erase

Use a new node member "endOfRange" instead
This commit is contained in:
2024-08-16 09:08:56 -07:00
parent 0711ec3831
commit 55a230c75e

View File

@@ -173,7 +173,7 @@ int BitSet::firstSetGeq(int i) const {
return -1;
}
enum Type {
enum Type : int8_t {
Type_Node0,
Type_Node3,
Type_Node16,
@@ -191,6 +191,8 @@ struct Node {
int32_t partialKeyLen;
int16_t numChildren;
bool entryPresent;
// Temp variable used to signal the end of the range during addWriteRange
bool endOfRange;
uint8_t parentsIndex;
/* end section that's copied to the next node */
@@ -625,6 +627,7 @@ template <class T> struct BoundedFreeListAllocator {
T *allocate(int partialKeyCapacity) {
T *result = allocate_helper(partialKeyCapacity);
result->endOfRange = false;
if constexpr (!std::is_same_v<T, Node0>) {
memset(result->children, 0, sizeof(result->children));
const auto z = InternalVersionT::zero;
@@ -1727,11 +1730,10 @@ void maybeDownsize(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
// Precondition: self is not the root. May invalidate nodes along the search
// path to self. May invalidate children of self->parent. Returns a pointer to
// the node after self. If erase invalidates the pointee of `dontInvalidate`, it
// will update it to its new pointee as well. Precondition: `self->entryPresent`
template <bool kCheckDontInvalidate = true>
// the node after self. Precondition: `self->entryPresent`
Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
bool logical, Node *&dontInvalidate) {
bool logical) {
++tls->accum.entries_erased;
assert(self->parent != nullptr);
@@ -1749,13 +1751,7 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
self->entryPresent = false;
if (self->numChildren != 0) {
const bool update = result == dontInvalidate;
maybeDownsize(self, tls, impl, result);
if constexpr (kCheckDontInvalidate) {
if (update) {
dontInvalidate = result;
}
}
return result;
}
@@ -1835,23 +1831,11 @@ Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
const bool update = result == dontInvalidate;
maybeDownsize(parent, tls, impl, result);
if constexpr (kCheckDontInvalidate) {
if (update) {
dontInvalidate = result;
}
}
return result;
}
Node *erase(Node *self, WriteContext *tls, ConflictSet::Impl *impl,
bool logical) {
Node *dummy;
return erase<false>(self, tls, impl, logical, dummy);
}
Node *nextSibling(Node *node) {
for (;;) {
if (node->parent == nullptr) {
@@ -3064,13 +3048,21 @@ void addWriteRange(Node *&root, std::span<const uint8_t> begin,
}
endNode->entry.rangeVersion = writeVersion;
for (beginNode = nextLogical(beginNode); beginNode != endNode;
beginNode = erase(beginNode, tls, impl, /*logical*/ true, endNode)) {
// Erase nodes in range
assert(!beginNode->endOfRange);
assert(!endNode->endOfRange);
endNode->endOfRange = true;
auto *iter = beginNode;
for (iter = nextLogical(iter); !iter->endOfRange;
iter = erase(iter, tls, impl, /*logical*/ true)) {
assert(!iter->endOfRange);
}
assert(iter->endOfRange);
iter->endOfRange = false;
// Inserting end trashed endNode's maxVersion. Fix that. Safe to call since
// the end key always has non-zero size.
fixupMaxVersion(endNode, tls);
// Inserting end trashed the last node's maxVersion. Fix that. Safe to call
// since the end key always has non-zero size.
fixupMaxVersion(iter, tls);
}
Node *firstGeqPhysical(Node *n, const std::span<const uint8_t> key) {