Convert checkPointRead to IteratorBase

This commit is contained in:
2024-11-22 15:25:51 -08:00
parent ee5972f946
commit 1fccb65bd8

View File

@@ -1929,14 +1929,118 @@ struct IteratorBase {
InternalVersionT exchangeMaxVersion(InternalVersionT); InternalVersionT exchangeMaxVersion(InternalVersionT);
InternalVersionT setMaxVersion(); InternalVersionT setMaxVersion();
TrivialSpan partialKey(); TrivialSpan partialKey();
IteratorBase getFirstChild();
bool checkRangeVersionOfFirstGeq(InternalVersionT readVersion);
struct ChildAndMaxVersion;
ChildAndMaxVersion getChildAndMaxVersion(int index);
IteratorBase getChildGeq(int index);
IteratorBase nextSibling();
private: protected:
Node *node; Node *node;
// index into children array of particular leaf type // index into children array of particular leaf type
int index; int index;
}; };
template <class T> struct Iterator : IteratorBase {}; struct IteratorBase::ChildAndMaxVersion {
IteratorBase child;
InternalVersionT maxVersion;
};
template <class T> struct Iterator : IteratorBase {
IteratorBase getFirstChild() {
return IteratorBase(::getFirstChild(static_cast<T *>(node)));
}
ChildAndMaxVersion getChildAndMaxVersion(int index) {
auto x = ::getChildAndMaxVersion(static_cast<T *>(node), index);
return {IteratorBase{x.child}, x.maxVersion};
}
IteratorBase getChildGeq(int index) {
return IteratorBase{::getChildGeq(static_cast<T *>(node), index)};
}
TrivialSpan partialKey() {
return {static_cast<T *>(node)->partialKey(), node->partialKeyLen};
}
};
TrivialSpan IteratorBase::partialKey() {
switch (node->getType()) {
case Type_Node0:
return as<Node0>().partialKey();
case Type_Node3:
return as<Node3>().partialKey();
case Type_Node16:
return as<Node16>().partialKey();
case Type_Node48:
return as<Node48>().partialKey();
case Type_Node256:
return as<Node256>().partialKey();
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
}
IteratorBase IteratorBase::getFirstChild() {
switch (node->getType()) {
case Type_Node0:
return as<Node0>().getFirstChild();
case Type_Node3:
return as<Node3>().getFirstChild();
case Type_Node16:
return as<Node16>().getFirstChild();
case Type_Node48:
return as<Node48>().getFirstChild();
case Type_Node256:
return as<Node256>().getFirstChild();
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
}
IteratorBase::ChildAndMaxVersion
IteratorBase::getChildAndMaxVersion(int index) {
switch (node->getType()) {
case Type_Node0:
return as<Node0>().getChildAndMaxVersion(index);
case Type_Node3:
return as<Node3>().getChildAndMaxVersion(index);
case Type_Node16:
return as<Node16>().getChildAndMaxVersion(index);
case Type_Node48:
return as<Node48>().getChildAndMaxVersion(index);
case Type_Node256:
return as<Node256>().getChildAndMaxVersion(index);
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
}
IteratorBase IteratorBase::getChildGeq(int index) {
switch (node->getType()) {
case Type_Node0:
return as<Node0>().getChildGeq(index);
case Type_Node3:
return as<Node3>().getChildGeq(index);
case Type_Node16:
return as<Node16>().getChildGeq(index);
case Type_Node48:
return as<Node48>().getChildGeq(index);
case Type_Node256:
return as<Node256>().getChildGeq(index);
default: // GCOVR_EXCL_LINE
__builtin_unreachable(); // GCOVR_EXCL_LINE
}
}
bool IteratorBase::checkRangeVersionOfFirstGeq(InternalVersionT readVersion) {
return ::checkRangeVersionOfFirstGeq(node, readVersion);
}
TaggedNodePointer nextSibling(Node *node);
IteratorBase IteratorBase::nextSibling() {
return IteratorBase{::nextSibling(node)};
}
// Precondition: self is not the root. May invalidate nodes along the search // 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 // path to self. May invalidate children of self->parent. Returns a pointer to
@@ -4437,7 +4541,7 @@ namespace {
// Logically this is the same as performing firstGeq and then checking against // Logically this is the same as performing firstGeq and then checking against
// point or range version according to cmp, but this version short circuits as // point or range version according to cmp, but this version short circuits as
// soon as it can prove that there's no conflict. // soon as it can prove that there's no conflict.
bool checkPointRead(Node *n, const TrivialSpan key, bool checkPointRead(IteratorBase n, const TrivialSpan key,
InternalVersionT readVersion, ReadContext *readContext) { InternalVersionT readVersion, ReadContext *readContext) {
++readContext->point_read_accum; ++readContext->point_read_accum;
#if DEBUG_VERBOSE && !defined(NDEBUG) #if DEBUG_VERBOSE && !defined(NDEBUG)
@@ -4446,54 +4550,54 @@ bool checkPointRead(Node *n, const TrivialSpan key,
auto remaining = key; auto remaining = key;
for (;; ++readContext->point_read_iterations_accum) { for (;; ++readContext->point_read_iterations_accum) {
if (remaining.size() == 0) { if (remaining.size() == 0) {
if (n->entryPresent) { if (n.entryPresent()) {
return n->entry.pointVersion <= readVersion; return n.getEntry().pointVersion <= readVersion;
} }
n = getFirstChild(n); return n.getFirstChild().checkRangeVersionOfFirstGeq(readVersion);
return checkRangeVersionOfFirstGeq(n, readVersion);
} }
auto [c, maxV] = getChildAndMaxVersion(n, remaining[0]); auto [c, maxV] = n.getChildAndMaxVersion(remaining[0]);
Node *child = c; IteratorBase child = c;
if (child == nullptr) { if (!child.valid()) {
auto c = getChildGeq(n, remaining[0]); auto c = n.getChildGeq(remaining[0]);
if (c != nullptr) { if (c.valid()) {
n = c; return c.checkRangeVersionOfFirstGeq(readVersion);
return checkRangeVersionOfFirstGeq(n, readVersion);
} else { } else {
n = nextSibling(n); n = n.nextSibling();
if (n == nullptr) { if (!n.valid()) {
return true; return true;
} }
return checkRangeVersionOfFirstGeq(n, readVersion); return n.checkRangeVersionOfFirstGeq(readVersion);
} }
} }
n = child; n = child;
remaining = remaining.subspan(1, remaining.size() - 1); remaining = remaining.subspan(1, remaining.size() - 1);
if (n->partialKeyLen > 0) { auto partialKey = n.partialKey();
int commonLen = std::min<int>(n->partialKeyLen, remaining.size()); if (partialKey.size() > 0) {
int i = longestCommonPrefix(n->partialKey(), remaining.data(), commonLen); int commonLen = std::min<int>(partialKey.size(), remaining.size());
int i =
longestCommonPrefix(partialKey.data(), remaining.data(), commonLen);
if (i < commonLen) { if (i < commonLen) {
auto c = n->partialKey()[i] <=> remaining[i]; auto c = partialKey[i] <=> remaining[i];
if (c > 0) { if (c > 0) {
return checkRangeVersionOfFirstGeq(n, readVersion); return n.checkRangeVersionOfFirstGeq(readVersion);
} else { } else {
n = nextSibling(n); n = n.nextSibling();
if (n == nullptr) { if (!n.valid()) {
return true; return true;
} }
return checkRangeVersionOfFirstGeq(n, readVersion); return n.checkRangeVersionOfFirstGeq(readVersion);
} }
} }
if (commonLen == n->partialKeyLen) { if (commonLen == partialKey.size()) {
// partial key matches // partial key matches
remaining = remaining.subspan(commonLen, remaining.size() - commonLen); remaining = remaining.subspan(commonLen, remaining.size() - commonLen);
} else if (n->partialKeyLen > remaining.size()) { } else if (partialKey.size() > remaining.size()) {
// n is the first physical node greater than remaining, and there's no // n is the first physical node greater than remaining, and there's no
// eq node // eq node
return checkRangeVersionOfFirstGeq(n, readVersion); return n.checkRangeVersionOfFirstGeq(readVersion);
} }
} }
@@ -4753,7 +4857,7 @@ bool checkRangeRead(Node *n, TrivialSpan begin, TrivialSpan end,
std::min(begin.size(), end.size())); std::min(begin.size(), end.size()));
if (lcp == begin.size() && end.size() == begin.size() + 1 && if (lcp == begin.size() && end.size() == begin.size() + 1 &&
end.back() == 0) { end.back() == 0) {
return checkPointRead(n, begin, readVersion, readContext); return checkPointRead(IteratorBase{n}, begin, readVersion, readContext);
} }
if (lcp == begin.size() - 1 && end.size() == begin.size() && if (lcp == begin.size() - 1 && end.size() == begin.size() &&
begin.back() + 1 == end.back()) { begin.back() + 1 == end.back()) {
@@ -4829,7 +4933,7 @@ struct __attribute__((visibility("hidden"))) ConflictSet::Impl {
} else { } else {
bool ok; bool ok;
if (reads[i].end.len == 0) { if (reads[i].end.len == 0) {
ok = checkPointRead(rootParent->children[0], ok = checkPointRead(IteratorBase{rootParent->children[0]},
TrivialSpan(reads[i].begin.p, reads[i].begin.len), TrivialSpan(reads[i].begin.p, reads[i].begin.len),
InternalVersionT(reads[i].readVersion), InternalVersionT(reads[i].readVersion),
&context.readContext); &context.readContext);