From bce4a8b2d870151bc192f693cc4844dec4d8d47b Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Thu, 9 May 2024 13:37:33 -0700 Subject: [PATCH] Implement firstGeq --- VersionedMap.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/VersionedMap.cpp b/VersionedMap.cpp index 9caa004..24ce4c5 100644 --- a/VersionedMap.cpp +++ b/VersionedMap.cpp @@ -352,6 +352,12 @@ auto operator<=>(const VersionedMap::Key &lhs, const Node &rhs) { return lhs.len <=> rhs.entry->keyLen; } +constexpr int orderToInt(std::strong_ordering o) { + return o == std::strong_ordering::less ? -1 + : o == std::strong_ordering::equal ? 0 + : 1; +} + struct Finger { void push(uint32_t node, bool dir) { searchPath[searchPathSize_] = node; @@ -413,8 +419,10 @@ private: struct VersionedMap::Impl { + // The last node is allowed to be 0, in which case this is the search path of + // where an entry would exist template - void move(Finger &finger, int64_t at, bool direction) { + void move(Finger &finger, int64_t at, bool direction) const { uint32_t c; if (finger.backNode() != 0 && (c = child(finger.backNode(), direction, at)) != 0) { @@ -431,7 +439,7 @@ struct VersionedMap::Impl { } template - uint32_t child(uint32_t node, bool which, int64_t at) { + uint32_t child(uint32_t node, bool which, int64_t at) const { static_assert(kOrder == std::memory_order_acquire || kOrder == std::memory_order_relaxed); auto &n = mm.base[node]; @@ -522,7 +530,7 @@ struct VersionedMap::Impl { int len; }; - Finger search(Key key, int64_t at) { + Finger search(Key key, int64_t at) const { Finger finger; bool ignored; finger.push(latestRoot, ignored); @@ -712,6 +720,7 @@ struct VersionedMap::Impl { } void setOldestVersion(int64_t oldestVersion) { + this->oldestVersion = oldestVersion; roots.setOldestVersion(oldestVersion); mm.gc(roots.roots(), roots.rootCount(), oldestVersion); } @@ -752,10 +761,14 @@ struct VersionedMap::Impl { roots.add(latestRoot, latestVersion); } + void firstGeq(const Key *key, const int64_t *version, Iterator *iterator, + int count) const; + MemManager mm; RootSet roots; // Only meaningful within the callstack of `addMutations` uint32_t latestRoot; + int64_t oldestVersion = 0; int64_t latestVersion = 0; }; @@ -787,7 +800,7 @@ void VersionedMap::addMutations(const Mutation *mutations, int numMutations, struct VersionedMap::Iterator::Impl { Finger finger; int64_t version; - VersionedMap::Impl *map; + const VersionedMap::Impl *map; int cmp; // True if this is a point mutation and a range mutation, and we're // materializing the range mutation instead of the point mutation. @@ -907,12 +920,46 @@ bool VersionedMap::Iterator::operator==(const Iterator &other) const { other.impl->materializeClearEndingHere; } +void VersionedMap::Impl::firstGeq(const Key *key, const int64_t *version, + Iterator *iterator, int count) const { + // TODO ILP! + for (int i = 0; i < count; ++i) { + // TODO re-use root if passed-in iterator version matches + auto finger = search(key[i], version[i]); + if (iterator[i].impl != nullptr) { + iterator[i].impl->~Impl(); + } + iterator[i].impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl(); + + if (finger.searchPathSize() == 0) { + iterator[i].impl->cmp = 1; + } else if (finger.backNode() == 0) { + iterator[i].impl->cmp = 1; + move(finger, version[i], true); + const auto &entry = *mm.base[finger.backNode()].entry; + iterator[i].impl->materializeClearEndingHere = + entry.clearTo() && entry.pointMutation(); + } else { + iterator[i].impl->cmp = 0; + } + + iterator[i].impl->finger = finger; + iterator[i].impl->version = version[i]; + iterator[i].impl->map = this; + } +} + bool VersionedMap::Iterator::operator!=(const Iterator &other) const { return !(*this == other); } int VersionedMap::Iterator::cmp() const { return impl->cmp; } +void VersionedMap::firstGeq(const Key *key, const int64_t *version, + Iterator *iterator, int count) const { + impl->firstGeq(key, version, iterator, count); +} + VersionedMap::Iterator VersionedMap::begin(int64_t version) const { VersionedMap::Iterator result; result.impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl(); @@ -1023,8 +1070,10 @@ int main() { } const int64_t v = 3; cast(versionedMap)->printInOrder(v); - for (auto iter = versionedMap.begin(v), end = versionedMap.end(v); - iter != end; ++iter) { + weaselab::VersionedMap::Key k = {(const uint8_t *)"aa", 2}; + weaselab::VersionedMap::Iterator iter; + versionedMap.firstGeq(&k, &v, &iter, 1); + for (auto end = versionedMap.end(v); iter != end; ++iter) { const auto &m = *iter; switch (m.type) { case weaselab::VersionedMap::Set: