diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 9423c88..2fd4735 100644 --- a/ConflictSet.cpp +++ b/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(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(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(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(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(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(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(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