diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 758d356..98a0cdd 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -1204,6 +1204,128 @@ TaggedNodePointer getChild(Node *self, uint8_t index) { } } +TaggedNodePointer *getChildUpdatingMaxVersion(Node0 *, + std::span &, + InternalVersionT) { + return nullptr; +} +TaggedNodePointer * +getChildUpdatingMaxVersion(Node3 *self, std::span &remaining, + InternalVersionT maxVersion) { + assert(remaining.size() > 0); + int index = remaining.front(); + auto key = remaining.subspan(1, remaining.size() - 1); + int i = getNodeIndex(self, index); + if (i < 0) { + return nullptr; + } + Node *c = self->children[i]; + int commonLen = std::min(c->partialKeyLen, key.size()); + int partialKeyIndex = + longestCommonPrefix(c->partialKey(), key.data(), commonLen); + if (partialKeyIndex < c->partialKeyLen) { + return nullptr; + } + remaining = key.subspan(c->partialKeyLen, key.size() - c->partialKeyLen); + self->childMaxVersion[i] = maxVersion; + return &self->children[i]; +} +TaggedNodePointer * +getChildUpdatingMaxVersion(Node16 *self, std::span &remaining, + InternalVersionT maxVersion) { + assert(remaining.size() > 0); + int index = remaining.front(); + auto key = remaining.subspan(1, remaining.size() - 1); + int i = getNodeIndex(self, index); + if (i < 0) { + return nullptr; + } + Node *c = self->children[i]; + int commonLen = std::min(c->partialKeyLen, key.size()); + int partialKeyIndex = + longestCommonPrefix(c->partialKey(), key.data(), commonLen); + if (partialKeyIndex < c->partialKeyLen) { + return nullptr; + } + remaining = key.subspan(c->partialKeyLen, key.size() - c->partialKeyLen); + self->childMaxVersion[i] = maxVersion; + return &self->children[i]; +} +TaggedNodePointer * +getChildUpdatingMaxVersion(Node48 *self, std::span &remaining, + InternalVersionT maxVersion) { + assert(remaining.size() > 0); + int index = remaining.front(); + auto key = remaining.subspan(1, remaining.size() - 1); + int i = self->index[index]; + if (i < 0) { + return nullptr; + } + Node *c = self->children[i]; + int commonLen = std::min(c->partialKeyLen, key.size()); + int partialKeyIndex = + longestCommonPrefix(c->partialKey(), key.data(), commonLen); + if (partialKeyIndex < c->partialKeyLen) { + return nullptr; + } + remaining = key.subspan(c->partialKeyLen, key.size() - c->partialKeyLen); + self->childMaxVersion[i] = maxVersion; + self->maxOfMax[i >> Node48::kMaxOfMaxShift] = + std::max(self->maxOfMax[i >> Node48::kMaxOfMaxShift], maxVersion); + return &self->children[i]; +} +TaggedNodePointer * +getChildUpdatingMaxVersion(Node256 *self, std::span &remaining, + InternalVersionT maxVersion) { + assert(remaining.size() > 0); + int index = remaining.front(); + auto key = remaining.subspan(1, remaining.size() - 1); + auto &n = self->children[index]; + if (n == nullptr) { + return nullptr; + } + Node *c = n; + int commonLen = std::min(c->partialKeyLen, key.size()); + int partialKeyIndex = + longestCommonPrefix(c->partialKey(), key.data(), commonLen); + if (partialKeyIndex < c->partialKeyLen) { + return nullptr; + } + remaining = key.subspan(c->partialKeyLen, key.size() - c->partialKeyLen); + self->childMaxVersion[index] = maxVersion; + self->maxOfMax[index >> Node256::kMaxOfMaxShift] = + std::max(self->maxOfMax[index >> Node256::kMaxOfMaxShift], maxVersion); + return &n; +} + +// Precondition: remaining.size() > 0 +// If a child of self lies along the search path of remaining, return a pointer +// to that child, update max version, and consume the matching prefix bytes from +// remaining. Otherwise return nullptr without changing the tree at all. +TaggedNodePointer * +getChildUpdatingMaxVersion(Node *self, std::span &remaining, + InternalVersionT maxVersion) { + switch (self->getType()) { + case Type_Node0: + return getChildUpdatingMaxVersion(static_cast(self), remaining, + maxVersion); + case Type_Node3: + return getChildUpdatingMaxVersion(static_cast(self), remaining, + maxVersion); + case Type_Node16: + return getChildUpdatingMaxVersion(static_cast(self), remaining, + maxVersion); + case Type_Node48: + return getChildUpdatingMaxVersion(static_cast(self), remaining, + maxVersion); + case Type_Node256: + return getChildUpdatingMaxVersion(static_cast(self), remaining, + maxVersion); + default: // GCOVR_EXCL_LINE + __builtin_unreachable(); // GCOVR_EXCL_LINE + } +} + struct ChildAndMaxVersion { TaggedNodePointer child; InternalVersionT maxVersion;