Prepare to fully canonicalize views
This commit is contained in:
@@ -54,7 +54,7 @@ void setAndClearPrev() {
|
|||||||
|
|
||||||
auto m = *iter++;
|
auto m = *iter++;
|
||||||
int64_t k = __builtin_bswap64(version);
|
int64_t k = __builtin_bswap64(version);
|
||||||
assert(m.version == version);
|
assert(m.notModifiedSince == version);
|
||||||
assert(m.param1Len == 8);
|
assert(m.param1Len == 8);
|
||||||
assert(m.param2Len == 8);
|
assert(m.param2Len == 8);
|
||||||
int64_t zero = __builtin_bswap64(0);
|
int64_t zero = __builtin_bswap64(0);
|
||||||
@@ -63,7 +63,7 @@ void setAndClearPrev() {
|
|||||||
assert(m.type == weaselab::VersionedMap::Clear);
|
assert(m.type == weaselab::VersionedMap::Clear);
|
||||||
|
|
||||||
m = *iter++;
|
m = *iter++;
|
||||||
assert(m.version == version);
|
assert(m.notModifiedSince == version);
|
||||||
assert(m.param1Len == 8);
|
assert(m.param1Len == 8);
|
||||||
assert(m.param2Len == 8);
|
assert(m.param2Len == 8);
|
||||||
assert(memcmp(m.param1, &k, 8) == 0);
|
assert(memcmp(m.param1, &k, 8) == 0);
|
||||||
|
4
Facade.h
4
Facade.h
@@ -191,8 +191,8 @@ struct Facade {
|
|||||||
for (auto iter = versioned.begin(version), end = versioned.end(version);
|
for (auto iter = versioned.begin(version), end = versioned.end(version);
|
||||||
iter != end; ++iter) {
|
iter != end; ++iter) {
|
||||||
auto m = *iter;
|
auto m = *iter;
|
||||||
assert(m.version <= version);
|
assert(m.notModifiedSince <= version);
|
||||||
if (m.version <= unversionedVersion) {
|
if (m.notModifiedSince <= unversionedVersion) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
switch (m.type) {
|
switch (m.type) {
|
||||||
|
@@ -1345,7 +1345,7 @@ VersionedMap::Iterator::operator*() const {
|
|||||||
result.param2 = impl->iter->getValue().p;
|
result.param2 = impl->iter->getValue().p;
|
||||||
result.param2Len = impl->iter->getValue().len;
|
result.param2Len = impl->iter->getValue().len;
|
||||||
}
|
}
|
||||||
result.version = impl->iter.insertVersion();
|
result.notModifiedSince = impl->iter.insertVersion();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@@ -27,7 +27,7 @@ printMutation(const weaselab::VersionedMap::Iterator::VersionedMutation &m) {
|
|||||||
printf("x%02x", c);
|
printf("x%02x", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("' @ %" PRId64 "\n", m.version);
|
printf("' @ %" PRId64 "\n", m.notModifiedSince);
|
||||||
break;
|
break;
|
||||||
case weaselab::VersionedMap::Clear:
|
case weaselab::VersionedMap::Clear:
|
||||||
printf("clear [");
|
printf("clear [");
|
||||||
@@ -48,7 +48,7 @@ printMutation(const weaselab::VersionedMap::Iterator::VersionedMutation &m) {
|
|||||||
printf("x%02x", c);
|
printf("x%02x", c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(") @ %" PRId64 "\n", m.version);
|
printf(") @ %" PRId64 "\n", m.notModifiedSince);
|
||||||
break;
|
break;
|
||||||
default: // GCOVR_EXCL_LINE
|
default: // GCOVR_EXCL_LINE
|
||||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||||
|
@@ -615,10 +615,9 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
|
|
||||||
// If `val` is set, then this is a point mutation at `latestVersion`.
|
// If `val` is set, then this is a point mutation at `latestVersion`.
|
||||||
// Otherwise it's the end of a range mutation at `latestVersion`.
|
// Otherwise it's the end of a range mutation at `latestVersion`.
|
||||||
// `finger` becomes the search path of `key`
|
// `finger` is a valid finger to the insertion path of `key` in the latest
|
||||||
|
// version (which can be obtained with `search`)
|
||||||
void insert(Key key, std::optional<Val> val, Finger &finger) {
|
void insert(Key key, std::optional<Val> val, Finger &finger) {
|
||||||
|
|
||||||
search<std::memory_order_relaxed>(key, latestRoot, latestVersion, finger);
|
|
||||||
const bool inserted = finger.backNode() == 0;
|
const bool inserted = finger.backNode() == 0;
|
||||||
|
|
||||||
int64_t pointVersion, rangeVersion;
|
int64_t pointVersion, rangeVersion;
|
||||||
@@ -878,9 +877,13 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
Finger iter;
|
Finger iter;
|
||||||
switch (m.type) {
|
switch (m.type) {
|
||||||
case Set: {
|
case Set: {
|
||||||
|
search<std::memory_order_relaxed>({m.param1, m.param1Len}, latestRoot,
|
||||||
|
latestVersion, iter);
|
||||||
insert({m.param1, m.param1Len}, {{m.param2, m.param2Len}}, iter);
|
insert({m.param1, m.param1Len}, {{m.param2, m.param2Len}}, iter);
|
||||||
} break;
|
} break;
|
||||||
case Clear: {
|
case Clear: {
|
||||||
|
search<std::memory_order_relaxed>({m.param1, m.param1Len}, latestRoot,
|
||||||
|
latestVersion, iter);
|
||||||
insert({m.param1, m.param1Len}, {{nullptr, -1}}, iter);
|
insert({m.param1, m.param1Len}, {{nullptr, -1}}, iter);
|
||||||
if (m.param2Len > 0) {
|
if (m.param2Len > 0) {
|
||||||
move<std::memory_order_relaxed, true>(iter, latestVersion);
|
move<std::memory_order_relaxed, true>(iter, latestVersion);
|
||||||
@@ -891,6 +894,8 @@ struct __attribute__((__visibility__("hidden"))) VersionedMap::Impl {
|
|||||||
}
|
}
|
||||||
// TODO reuse finger? It should be one rank away from its insertion
|
// TODO reuse finger? It should be one rank away from its insertion
|
||||||
// point
|
// point
|
||||||
|
search<std::memory_order_relaxed>({m.param2, m.param2Len}, latestRoot,
|
||||||
|
latestVersion, iter);
|
||||||
insert({m.param2, m.param2Len}, {}, iter);
|
insert({m.param2, m.param2Len}, {}, iter);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
@@ -86,16 +86,13 @@ struct __attribute__((__visibility__("default"))) VersionedMap {
|
|||||||
/** The version of the most recent call to `setOldestVersion`. */
|
/** The version of the most recent call to `setOldestVersion`. */
|
||||||
int64_t getOldestVersion() const;
|
int64_t getOldestVersion() const;
|
||||||
|
|
||||||
/** Iterates through a canonicalized[1] view of all the mutations
|
/** Iterates through a canonicalized view of all the mutations
|
||||||
* from `oldestVersion` to the iterator's version. There may be mutations from
|
* from `oldestVersion` to the iterator's version. There may be mutations from
|
||||||
* versions < `oldestVersion`, but they won't affect the result, and can be
|
* versions < `oldestVersion`, but they won't affect the result, and can be
|
||||||
* ignored if desired. It's thread-safe to operate on an iterator concurrently
|
* ignored if desired. It's thread-safe to operate on an iterator concurrently
|
||||||
* with any method of `VersionedMap`, as long as it's not invalidated by
|
* with any method of `VersionedMap`, as long as it's not invalidated by
|
||||||
* `setOldestVersion`.
|
* `setOldestVersion`.
|
||||||
* @warning must not outlive its `VersionedMap`.
|
* @warning must not outlive its `VersionedMap`.
|
||||||
*
|
|
||||||
* [1]: Clears at different versions may be adjacent. This is necessary for
|
|
||||||
* precisely tracking at what version the mutations take effect.
|
|
||||||
*/
|
*/
|
||||||
struct Iterator {
|
struct Iterator {
|
||||||
|
|
||||||
@@ -114,7 +111,10 @@ struct __attribute__((__visibility__("default"))) VersionedMap {
|
|||||||
int param1Len;
|
int param1Len;
|
||||||
int param2Len;
|
int param2Len;
|
||||||
MutationType type;
|
MutationType type;
|
||||||
int64_t version;
|
/** The set of keys modified by this mutation have not been modified since
|
||||||
|
* this version. They were not necessarily modified at this version
|
||||||
|
* though. */
|
||||||
|
int64_t notModifiedSince;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** iter must not be `end()`. Memory pointed-to by return value is valid as
|
/** iter must not be `end()`. Memory pointed-to by return value is valid as
|
||||||
|
Reference in New Issue
Block a user