Change eraseChild to erase
This commit is contained in:
163
ConflictSet.cpp
163
ConflictSet.cpp
@@ -462,6 +462,8 @@ int64_t getChildMaxVersion(Node *self, uint8_t index) {
|
||||
// Precondition - an entry for index must exist in the node
|
||||
int64_t &maxVersion(Node *n, ConflictSet::Impl *);
|
||||
|
||||
Node *&getInTree(Node *n, ConflictSet::Impl *);
|
||||
|
||||
Node *getChild(Node *self, uint8_t index) {
|
||||
if (self->type <= Type::Node16) {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
@@ -703,61 +705,6 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
}
|
||||
}
|
||||
|
||||
// Precondition - an entry for index must exist in the node
|
||||
void eraseChild(Node *self, uint8_t index, NodeAllocators *allocators) {
|
||||
auto *child = getChildExists(self, index);
|
||||
switch (child->type) {
|
||||
case Type::Node0:
|
||||
allocators->node0.release((Node0 *)child);
|
||||
break;
|
||||
case Type::Node4:
|
||||
allocators->node4.release((Node4 *)child);
|
||||
break;
|
||||
case Type::Node16:
|
||||
allocators->node16.release((Node16 *)child);
|
||||
break;
|
||||
case Type::Node48:
|
||||
allocators->node48.release((Node48 *)child);
|
||||
break;
|
||||
case Type::Node256:
|
||||
allocators->node256.release((Node256 *)child);
|
||||
break;
|
||||
}
|
||||
|
||||
if (self->type <= Type::Node16) {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
int nodeIndex = getNodeIndex(self16, index);
|
||||
memmove(self16->index + nodeIndex, self16->index + nodeIndex + 1,
|
||||
sizeof(self16->index[0]) * (self->numChildren - (nodeIndex + 1)));
|
||||
memmove(self16->children + nodeIndex, self16->children + nodeIndex + 1,
|
||||
sizeof(self16->children[0]) * // NOLINT
|
||||
(self->numChildren - (nodeIndex + 1)));
|
||||
} else if (self->type == Type::Node48) {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
self48->bitSet.reset(index);
|
||||
int8_t toRemoveChildrenIndex = std::exchange(self48->index[index], -1);
|
||||
int8_t lastChildrenIndex = --self48->nextFree;
|
||||
assert(toRemoveChildrenIndex >= 0);
|
||||
assert(lastChildrenIndex >= 0);
|
||||
if (toRemoveChildrenIndex != lastChildrenIndex) {
|
||||
self48->children[toRemoveChildrenIndex] =
|
||||
self48->children[lastChildrenIndex];
|
||||
self48
|
||||
->index[self48->children[toRemoveChildrenIndex].child->parentsIndex] =
|
||||
toRemoveChildrenIndex;
|
||||
}
|
||||
} else {
|
||||
auto *self256 = static_cast<Node256 *>(self);
|
||||
self256->bitSet.reset(index);
|
||||
self256->children[index].child = nullptr;
|
||||
}
|
||||
--self->numChildren;
|
||||
if (self->numChildren == 0 && !self->entryPresent &&
|
||||
self->parent != nullptr) {
|
||||
eraseChild(self->parent, self->parentsIndex, allocators);
|
||||
}
|
||||
}
|
||||
|
||||
Node *nextPhysical(Node *node) {
|
||||
int index = -1;
|
||||
for (;;) {
|
||||
@@ -780,6 +727,74 @@ Node *nextLogical(Node *node) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// Precondition: self is not the root
|
||||
Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl) {
|
||||
assert(self->parent != nullptr);
|
||||
|
||||
Node *parent = self->parent;
|
||||
uint8_t parentsIndex = self->parentsIndex;
|
||||
|
||||
auto *result = nextLogical(self);
|
||||
self->entryPresent = false;
|
||||
if (self->numChildren != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
allocators->node0.release((Node0 *)self);
|
||||
break;
|
||||
case Type::Node4:
|
||||
allocators->node4.release((Node4 *)self);
|
||||
break;
|
||||
case Type::Node16:
|
||||
allocators->node16.release((Node16 *)self);
|
||||
break;
|
||||
case Type::Node48:
|
||||
allocators->node48.release((Node48 *)self);
|
||||
break;
|
||||
case Type::Node256:
|
||||
allocators->node256.release((Node256 *)self);
|
||||
break;
|
||||
}
|
||||
|
||||
if (parent->type <= Type::Node16) {
|
||||
auto *parent16 = static_cast<Node16 *>(parent);
|
||||
int nodeIndex = getNodeIndex(parent16, parentsIndex);
|
||||
assert(nodeIndex >= 0);
|
||||
memmove(parent16->index + nodeIndex, parent16->index + nodeIndex + 1,
|
||||
sizeof(parent16->index[0]) *
|
||||
(parent->numChildren - (nodeIndex + 1)));
|
||||
memmove(parent16->children + nodeIndex, parent16->children + nodeIndex + 1,
|
||||
sizeof(parent16->children[0]) *
|
||||
(parent->numChildren - (nodeIndex + 1)));
|
||||
} else if (parent->type == Type::Node48) {
|
||||
auto *parent48 = static_cast<Node48 *>(parent);
|
||||
parent48->bitSet.reset(parentsIndex);
|
||||
int8_t toRemoveChildrenIndex =
|
||||
std::exchange(parent48->index[parentsIndex], -1);
|
||||
int8_t lastChildrenIndex = --parent48->nextFree;
|
||||
assert(toRemoveChildrenIndex >= 0);
|
||||
assert(lastChildrenIndex >= 0);
|
||||
if (toRemoveChildrenIndex != lastChildrenIndex) {
|
||||
parent48->children[toRemoveChildrenIndex] =
|
||||
parent48->children[lastChildrenIndex];
|
||||
parent48->index[parent48->children[toRemoveChildrenIndex]
|
||||
.child->parentsIndex] = toRemoveChildrenIndex;
|
||||
}
|
||||
} else {
|
||||
auto *parent256 = static_cast<Node256 *>(parent);
|
||||
parent256->bitSet.reset(parentsIndex);
|
||||
parent256->children[parentsIndex].child = nullptr;
|
||||
}
|
||||
--parent->numChildren;
|
||||
if (parent->numChildren == 0 && !parent->entryPresent &&
|
||||
parent->parent != nullptr) {
|
||||
erase(parent, allocators, impl);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct Iterator {
|
||||
Node *n;
|
||||
int cmp;
|
||||
@@ -1765,13 +1780,8 @@ void addWriteRange(Node *&root, int64_t oldestVersion,
|
||||
assert(beginNode->entryPresent);
|
||||
}
|
||||
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;) {
|
||||
auto *old = beginNode;
|
||||
beginNode = nextLogical(beginNode);
|
||||
old->entryPresent = false;
|
||||
if (old->numChildren == 0 && old->parent != nullptr) {
|
||||
eraseChild(old->parent, old->parentsIndex, allocators);
|
||||
}
|
||||
for (beginNode = nextLogical(beginNode); beginNode != endNode;
|
||||
beginNode = erase(beginNode, allocators, impl)) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1881,34 +1891,34 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
|
||||
if (keyUpdates < 100) {
|
||||
return;
|
||||
}
|
||||
Node *prev = firstGeq(root, removalKey).n;
|
||||
Node *n = firstGeq(root, removalKey).n;
|
||||
// There's no way to erase removalKey without introducing a key after it
|
||||
assert(prev != nullptr);
|
||||
assert(n != nullptr);
|
||||
// Don't erase the root
|
||||
if (n == root) {
|
||||
n = nextLogical(n);
|
||||
}
|
||||
for (; keyUpdates > 0; --keyUpdates) {
|
||||
Node *n = nextLogical(prev);
|
||||
if (n == nullptr) {
|
||||
removalKey = {};
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::max(prev->entry.pointVersion, prev->entry.rangeVersion) <=
|
||||
if (std::max(n->entry.pointVersion, n->entry.rangeVersion) <=
|
||||
oldestVersion) {
|
||||
// Any transaction prev would have prevented from committing is
|
||||
// Any transaction n would have prevented from committing is
|
||||
// going to fail with TooOld anyway.
|
||||
|
||||
// There's no way to insert a range such that range version of the right
|
||||
// node is greater than the point version of the left node
|
||||
assert(n->entry.rangeVersion <= oldestVersion);
|
||||
prev->entryPresent = false;
|
||||
if (prev->numChildren == 0 && prev->parent != nullptr) {
|
||||
eraseChild(prev->parent, prev->parentsIndex, &allocators);
|
||||
}
|
||||
n = erase(n, &allocators, this);
|
||||
} else {
|
||||
n = nextLogical(n);
|
||||
}
|
||||
|
||||
prev = n;
|
||||
}
|
||||
removalKeyArena = Arena();
|
||||
removalKey = getSearchPath(removalKeyArena, prev);
|
||||
removalKey = getSearchPath(removalKeyArena, n);
|
||||
}
|
||||
|
||||
explicit Impl(int64_t oldestVersion) : oldestVersion(oldestVersion) {
|
||||
@@ -1954,6 +1964,11 @@ int64_t &maxVersion(Node *n, ConflictSet::Impl *impl) {
|
||||
}
|
||||
}
|
||||
|
||||
Node *&getInTree(Node *n, ConflictSet::Impl *impl) {
|
||||
return n->parent == nullptr ? impl->root
|
||||
: getChildExists(n->parent, n->parentsIndex);
|
||||
}
|
||||
|
||||
// ==================== END IMPLEMENTATION ====================
|
||||
|
||||
// GCOVR_EXCL_START
|
||||
|
Reference in New Issue
Block a user