From 5111834a0b20caa19d4240542f56b70479186620 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Thu, 9 May 2024 14:25:03 -0700 Subject: [PATCH] Allow search to search at any version And re-use non-null iterators in firstGeq --- VersionedMap.cpp | 58 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/VersionedMap.cpp b/VersionedMap.cpp index b3687da..9733b94 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -368,6 +368,10 @@ struct Finger { assert(searchPathSize_ > 0); --searchPathSize_; } + uint32_t root() const { + assert(searchPathSize_ > 0); + return searchPath[0]; + } uint32_t backNode() const { assert(searchPathSize_ > 0); return searchPath[searchPathSize_ - 1]; @@ -530,10 +534,15 @@ struct VersionedMap::Impl { int len; }; - template Finger search(Key key, int64_t at) const { + template + Finger search(Key key, T root, int64_t version) const { + static_assert(std::is_same_v); Finger finger; + if (root == 0) { + return finger; + } bool ignored; - finger.push(latestRoot, ignored); + finger.push(root, ignored); // Initialize finger to the search path of `key` for (;;) { @@ -546,7 +555,7 @@ struct VersionedMap::Impl { // No duplicates break; } - finger.push(child(n, c > 0, latestVersion), c > 0); + finger.push(child(n, c > 0, version), c > 0); } return finger; } @@ -744,8 +753,8 @@ struct VersionedMap::Impl { case Clear: { insert({m.param1, m.param1Len}, {{nullptr, -1}}); if (m.param2Len > 0) { - auto iter = search({m.param1, m.param1Len}, - latestVersion); + auto iter = search( + {m.param1, m.param1Len}, latestRoot, latestVersion); move(iter, latestVersion, true); while (iter.searchPathSize() > 0 && mm.base[iter.backNode()] < Key{m.param2, m.param2Len}) { @@ -755,6 +764,7 @@ struct VersionedMap::Impl { } } break; default: // GCOVR_EXCL_LINE + assert(false); // GCOVR_EXCL_LINE __builtin_unreachable(); // GCOVR_EXCL_LINE } } @@ -874,10 +884,14 @@ VersionedMap::Iterator &VersionedMap::Iterator::operator++() { } impl->map->move(impl->finger, impl->version, true); - impl->materializeClearEndingHere = - impl->finger.searchPathSize() > 0 && - impl->map->mm.base[impl->finger.backNode()].entry->pointMutation() && - impl->map->mm.base[impl->finger.backNode()].entry->clearTo(); + if (impl->finger.searchPathSize() > 0) { + const auto &entry = *impl->map->mm.base[impl->finger.backNode()].entry; + impl->materializeClearEndingHere = entry.pointMutation() && entry.clearTo(); + assert(entry.pointVersion <= impl->version); + assert(entry.rangeVersion <= impl->version); + } else { + impl->materializeClearEndingHere = false; + } return *this; } @@ -923,13 +937,21 @@ bool VersionedMap::Iterator::operator==(const Iterator &other) const { void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version, Iterator *iterator, int count) const { // TODO ILP! + auto handle = roots.getThreadSafeHandle(); for (int i = 0; i < count; ++i) { - // TODO re-use root if passed-in iterator version matches - auto finger = search(key[i], version[i]); + + uint32_t root; if (iterator[i].impl != nullptr) { + root = iterator[i].impl->version == version[i] + ? iterator[i].impl->finger.root() + : handle.rootForVersion(version[i]); iterator[i].impl->~Impl(); + new (iterator[i].impl) Iterator::Impl(); + } else { + root = handle.rootForVersion(version[i]); + iterator[i].impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl(); } - iterator[i].impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl(); + auto finger = search(key[i], root, version[i]); if (finger.searchPathSize() == 0) { iterator[i].impl->cmp = 1; @@ -937,6 +959,7 @@ void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version, iterator[i].impl->cmp = 1; move(finger, version[i], true); if (finger.searchPathSize() > 0) { + assert(finger.backNode() != 0); const auto &entry = *mm.base[finger.backNode()].entry; iterator[i].impl->materializeClearEndingHere = entry.clearTo() && entry.pointMutation(); @@ -974,7 +997,7 @@ VersionedMap::Iterator VersionedMap::begin(int64_t version) const { result.impl->finger.pop(); } else { uint32_t c; - while ((c = impl->child( + while ((c = impl->child( result.impl->finger.backNode(), false, version)) != 0) { result.impl->finger.push(c, false); } @@ -1048,6 +1071,8 @@ VersionedMap::Impl *cast(const VersionedMap &m) { #ifdef ENABLE_MAIN #include +void breakpoint_me() {} + int main() { { weaselab::VersionedMap versionedMap{0}; @@ -1076,11 +1101,14 @@ int main() { }; versionedMap.addMutations(m, sizeof(m) / sizeof(m[0]), 3); } - const int64_t v = 3; + const int64_t v = 2; cast(versionedMap)->printInOrder(v); - weaselab::VersionedMap::Key k = {(const uint8_t *)"zz", 2}; + weaselab::VersionedMap::Key k = {(const uint8_t *)"a", 1}; weaselab::VersionedMap::Iterator iter; versionedMap.firstGeq(&k, &v, &iter, 1); + auto begin = versionedMap.begin(v); + assert(iter == begin); + breakpoint_me(); for (auto end = versionedMap.end(v); iter != end; ++iter) { const auto &m = *iter; switch (m.type) {