diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 8b2f4b6..2100a7c 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -3040,6 +3040,7 @@ struct CheckJob { namespace check_point_read_state_machine { CheckJob::continuation down_left_spine(CheckJob *job); +CheckJob::continuation iter(CheckJob *job); // 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 @@ -3049,21 +3050,45 @@ CheckJob::continuation begin(CheckJob *job) { #if DEBUG_VERBOSE && !defined(NDEBUG) fprintf(stderr, "Check point read: %s\n", printable(key).c_str()); #endif - for (;; ++job->tls->point_read_iterations_accum) { - if (job->begin.size() == 0) { - if (job->n->entryPresent) { - job->setResult(job->n->entry.pointVersion <= job->readVersion); + return iter(job); +} + +CheckJob::continuation iter(CheckJob *job) { + if (job->begin.size() == 0) { + if (job->n->entryPresent) { + job->setResult(job->n->entry.pointVersion <= job->readVersion); + return nullptr; // Done + } + job->n = getFirstChildExists(job->n); + return down_left_spine; + } + + auto [child, maxV] = getChildAndMaxVersion(job->n, job->begin[0]); + if (child == nullptr) { + auto c = getChildGeq(job->n, job->begin[0]); + if (c != nullptr) { + job->n = c; + return down_left_spine; + } else { + job->n = nextSibling(job->n); + if (job->n == nullptr) { + job->setResult(true); return nullptr; // Done } - job->n = getFirstChildExists(job->n); return down_left_spine; } + } - auto [child, maxV] = getChildAndMaxVersion(job->n, job->begin[0]); - if (child == nullptr) { - auto c = getChildGeq(job->n, job->begin[0]); - if (c != nullptr) { - job->n = c; + job->n = child; + job->begin = job->begin.subspan(1, job->begin.size() - 1); + + if (job->n->partialKeyLen > 0) { + int commonLen = std::min(job->n->partialKeyLen, job->begin.size()); + int i = + longestCommonPrefix(job->n->partialKey(), job->begin.data(), commonLen); + if (i < commonLen) { + auto c = job->n->partialKey()[i] <=> job->begin[i]; + if (c > 0) { return down_left_spine; } else { job->n = nextSibling(job->n); @@ -3074,44 +3099,24 @@ CheckJob::continuation begin(CheckJob *job) { return down_left_spine; } } - - job->n = child; - job->begin = job->begin.subspan(1, job->begin.size() - 1); - - if (job->n->partialKeyLen > 0) { - int commonLen = std::min(job->n->partialKeyLen, job->begin.size()); - int i = longestCommonPrefix(job->n->partialKey(), job->begin.data(), - commonLen); - if (i < commonLen) { - auto c = job->n->partialKey()[i] <=> job->begin[i]; - if (c > 0) { - return down_left_spine; - } else { - job->n = nextSibling(job->n); - if (job->n == nullptr) { - job->setResult(true); - return nullptr; // Done - } - return down_left_spine; - } - } - if (commonLen == job->n->partialKeyLen) { - // partial key matches - job->begin = - job->begin.subspan(commonLen, job->begin.size() - commonLen); - } else if (job->n->partialKeyLen > int(job->begin.size())) { - // n is the first physical node greater than remaining, and there's no - // eq node - return down_left_spine; - } - } - - if (maxV <= job->readVersion) { - ++job->tls->point_read_short_circuit_accum; - job->setResult(true); - return nullptr; // Done + if (commonLen == job->n->partialKeyLen) { + // partial key matches + job->begin = job->begin.subspan(commonLen, job->begin.size() - commonLen); + } else if (job->n->partialKeyLen > int(job->begin.size())) { + // n is the first physical node greater than remaining, and there's no + // eq node + return down_left_spine; } } + + if (maxV <= job->readVersion) { + ++job->tls->point_read_short_circuit_accum; + job->setResult(true); + return nullptr; // Done + } + + ++job->tls->point_read_iterations_accum; + return iter; } CheckJob::continuation down_left_spine(CheckJob *job) {