Implement Iterator
This commit is contained in:
201
VersionedMap.cpp
201
VersionedMap.cpp
@@ -400,7 +400,7 @@ struct VersionedMap::Impl {
|
||||
if (finger.backNode() != 0 &&
|
||||
(c = child<kOrder>(finger.backNode(), direction, at)) != 0) {
|
||||
finger.push(c, direction);
|
||||
while (auto c = child<kOrder>(finger.backNode(), !direction, at) != 0) {
|
||||
while ((c = child<kOrder>(finger.backNode(), !direction, at)) != 0) {
|
||||
finger.push(c, !direction);
|
||||
}
|
||||
} else {
|
||||
@@ -755,6 +755,159 @@ void VersionedMap::addMutations(const Mutation *mutations, int numMutations,
|
||||
impl->addMutations(mutations, numMutations, version);
|
||||
}
|
||||
|
||||
struct VersionedMap::Iterator::Impl {
|
||||
Finger finger;
|
||||
int64_t version;
|
||||
VersionedMap::Impl *map;
|
||||
int cmp;
|
||||
bool materializeClearEndingHere = false;
|
||||
};
|
||||
|
||||
VersionedMap::Iterator::~Iterator() {
|
||||
if (impl != nullptr) {
|
||||
impl->~Impl();
|
||||
free(impl);
|
||||
}
|
||||
}
|
||||
|
||||
VersionedMap::Iterator::Iterator(const Iterator &other)
|
||||
: impl(new(malloc(sizeof(Impl))) Impl(*other.impl)) {}
|
||||
|
||||
VersionedMap::Iterator &
|
||||
VersionedMap::Iterator::operator=(const Iterator &other) {
|
||||
if (impl != nullptr) {
|
||||
impl->~Impl();
|
||||
free(impl);
|
||||
}
|
||||
impl = new (malloc(sizeof(Impl))) Impl(*other.impl);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VersionedMap::Iterator::Iterator(Iterator &&other) noexcept
|
||||
: impl(std::exchange(other.impl, nullptr)) {}
|
||||
|
||||
VersionedMap::Iterator &
|
||||
VersionedMap::Iterator::operator=(Iterator &&other) noexcept {
|
||||
if (impl != nullptr) {
|
||||
impl->~Impl();
|
||||
free(impl);
|
||||
}
|
||||
impl = std::exchange(other.impl, nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
VersionedMap::Mutation VersionedMap::Iterator::operator*() const {
|
||||
assert(impl->finger.backNode() != 0);
|
||||
assert(impl->finger.searchPathSize() != 0);
|
||||
const auto &entry = *impl->map->mm.base[impl->finger.backNode()].entry;
|
||||
if (impl->materializeClearEndingHere) {
|
||||
assert(entry.clearTo);
|
||||
auto prev = *this;
|
||||
--prev;
|
||||
const auto &prevEntry =
|
||||
*prev.impl->map->mm.base[prev.impl->finger.backNode()].entry;
|
||||
return {prevEntry.getKey(), entry.getKey(), prevEntry.keyLen + 1,
|
||||
entry.keyLen, Clear};
|
||||
}
|
||||
if (entry.valLen >= 0) {
|
||||
return {entry.getKey(), entry.getVal(), entry.keyLen, entry.valLen, Set};
|
||||
} else {
|
||||
return {entry.getKey(), nullptr, entry.keyLen, -1, Clear};
|
||||
}
|
||||
}
|
||||
|
||||
VersionedMap::Iterator &VersionedMap::Iterator::operator++() {
|
||||
const auto &entry = *impl->map->mm.base[impl->finger.backNode()].entry;
|
||||
if (impl->materializeClearEndingHere) {
|
||||
assert(entry.clearTo);
|
||||
impl->materializeClearEndingHere = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
impl->map->move<std::memory_order_acquire>(impl->finger, impl->version, true);
|
||||
impl->materializeClearEndingHere =
|
||||
impl->finger.searchPathSize() > 0 &&
|
||||
impl->map->mm.base[impl->finger.backNode()].entry->clearTo;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
VersionedMap::Iterator VersionedMap::Iterator::operator++(int) {
|
||||
auto result = *this;
|
||||
++*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
VersionedMap::Iterator &VersionedMap::Iterator::operator--() {
|
||||
const auto &entry = *impl->map->mm.base[impl->finger.backNode()].entry;
|
||||
if (entry.clearTo && !impl->materializeClearEndingHere) {
|
||||
impl->materializeClearEndingHere = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
impl->map->move<std::memory_order_acquire>(impl->finger, impl->version,
|
||||
false);
|
||||
impl->materializeClearEndingHere = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VersionedMap::Iterator VersionedMap::Iterator::operator--(int) {
|
||||
auto result = *this;
|
||||
--*this;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool VersionedMap::Iterator::operator==(const Iterator &other) const {
|
||||
assert(impl->map == other.impl->map);
|
||||
assert(impl->version == other.impl->version);
|
||||
if (impl->finger.searchPathSize() == 0 ||
|
||||
other.impl->finger.searchPathSize() == 0) {
|
||||
return impl->finger.searchPathSize() == other.impl->finger.searchPathSize();
|
||||
}
|
||||
return impl->finger.backNode() == other.impl->finger.backNode() &&
|
||||
impl->materializeClearEndingHere ==
|
||||
other.impl->materializeClearEndingHere;
|
||||
}
|
||||
|
||||
bool VersionedMap::Iterator::operator!=(const Iterator &other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
int VersionedMap::Iterator::cmp() const { return impl->cmp; }
|
||||
|
||||
VersionedMap::Iterator VersionedMap::begin(int64_t version) const {
|
||||
VersionedMap::Iterator result;
|
||||
result.impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl();
|
||||
result.impl->cmp = 1;
|
||||
|
||||
bool ignored;
|
||||
result.impl->finger.push(
|
||||
impl->roots.getThreadSafeHandle().rootForVersion(version), ignored);
|
||||
if (result.impl->finger.backNode() == 0) {
|
||||
result.impl->finger.pop();
|
||||
} else {
|
||||
uint32_t c;
|
||||
while ((c = impl->child<std::memory_order_relaxed>(
|
||||
result.impl->finger.backNode(), false, version)) != 0) {
|
||||
result.impl->finger.push(c, false);
|
||||
}
|
||||
}
|
||||
result.impl->map = impl;
|
||||
result.impl->materializeClearEndingHere = false;
|
||||
result.impl->version = version;
|
||||
return result;
|
||||
}
|
||||
|
||||
VersionedMap::Iterator VersionedMap::end(int64_t version) const {
|
||||
VersionedMap::Iterator result;
|
||||
result.impl = new (malloc(sizeof(Iterator::Impl))) Iterator::Impl();
|
||||
result.impl->cmp = 1;
|
||||
result.impl->map = impl;
|
||||
result.impl->materializeClearEndingHere = false;
|
||||
result.impl->version = version;
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== END IMPLEMENTATION ====================
|
||||
|
||||
// GCOVR_EXCL_START
|
||||
@@ -791,6 +944,12 @@ void VersionedMap::Impl::printInOrderHelper(int64_t version, uint32_t node,
|
||||
depth + 1);
|
||||
}
|
||||
|
||||
VersionedMap::Impl *cast(const VersionedMap &m) {
|
||||
VersionedMap::Impl *result;
|
||||
memcpy(&result, &m, sizeof(void *));
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace weaselab
|
||||
|
||||
#ifdef ENABLE_MAIN
|
||||
@@ -798,7 +957,7 @@ void VersionedMap::Impl::printInOrderHelper(int64_t version, uint32_t node,
|
||||
|
||||
int main() {
|
||||
{
|
||||
weaselab::VersionedMap::Impl impl;
|
||||
weaselab::VersionedMap versionedMap{0};
|
||||
{
|
||||
weaselab::VersionedMap::Mutation m[] = {
|
||||
{(const uint8_t *)"a", nullptr, 1, 0, weaselab::VersionedMap::Set},
|
||||
@@ -808,23 +967,53 @@ int main() {
|
||||
{(const uint8_t *)"e", nullptr, 1, 0, weaselab::VersionedMap::Set},
|
||||
{(const uint8_t *)"f", nullptr, 1, 0, weaselab::VersionedMap::Set},
|
||||
};
|
||||
impl.addMutations(m, sizeof(m) / sizeof(m[0]), 1);
|
||||
versionedMap.addMutations(m, sizeof(m) / sizeof(m[0]), 1);
|
||||
}
|
||||
{
|
||||
weaselab::VersionedMap::Mutation m[] = {
|
||||
{(const uint8_t *)"a", (const uint8_t *)"d", 1, 1,
|
||||
weaselab::VersionedMap::Clear},
|
||||
};
|
||||
impl.addMutations(m, sizeof(m) / sizeof(m[0]), 2);
|
||||
versionedMap.addMutations(m, sizeof(m) / sizeof(m[0]), 2);
|
||||
}
|
||||
{
|
||||
weaselab::VersionedMap::Mutation m[] = {
|
||||
{(const uint8_t *)"b", (const uint8_t *)"", 1, 0,
|
||||
weaselab::VersionedMap::Clear},
|
||||
};
|
||||
impl.addMutations(m, sizeof(m) / sizeof(m[0]), 3);
|
||||
versionedMap.addMutations(m, sizeof(m) / sizeof(m[0]), 3);
|
||||
}
|
||||
cast(versionedMap)->printInOrder(3);
|
||||
for (auto iter = versionedMap.begin(3), end = versionedMap.end(3);
|
||||
iter != end; ++iter) {
|
||||
const auto &m = *iter;
|
||||
switch (m.type) {
|
||||
case weaselab::VersionedMap::Set:
|
||||
printf("set ");
|
||||
for (int i = 0; i < m.param1Len; ++i) {
|
||||
printf("x%02x", m.param1[i]);
|
||||
}
|
||||
printf(" -> ");
|
||||
for (int i = 0; i < m.param2Len; ++i) {
|
||||
printf("x%02x", m.param2[i]);
|
||||
}
|
||||
printf("\n");
|
||||
break;
|
||||
case weaselab::VersionedMap::Clear:
|
||||
printf("clear [");
|
||||
for (int i = 0; i < m.param1Len; ++i) {
|
||||
printf("x%02x", m.param1[i]);
|
||||
}
|
||||
printf(", ");
|
||||
for (int i = 0; i < m.param2Len; ++i) {
|
||||
printf("x%02x", m.param2[i]);
|
||||
}
|
||||
printf(")\n");
|
||||
break;
|
||||
default: // GCOVR_EXCL_LINE
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
}
|
||||
}
|
||||
impl.printInOrder(3);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
Reference in New Issue
Block a user