Prepare for firstGeq to be safe on foreign threads
This commit is contained in:
101
VersionedMap.cpp
101
VersionedMap.cpp
@@ -1,4 +1,5 @@
|
||||
#include "VersionedMap.h"
|
||||
#include "RootSet.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <atomic>
|
||||
@@ -315,98 +316,6 @@ private:
|
||||
uint32_t freeList = 0;
|
||||
};
|
||||
|
||||
struct RootSet {
|
||||
|
||||
/// Register the root node for version after adding mutations
|
||||
void add(uint32_t node, int64_t version) {
|
||||
if (end == 0) {
|
||||
nodes[end] = node;
|
||||
versions[end] = version;
|
||||
++end;
|
||||
return;
|
||||
}
|
||||
if (nodes[end - 1] == node) {
|
||||
return;
|
||||
}
|
||||
if (end == capacity) {
|
||||
capacity *= 2;
|
||||
nodes = (uint32_t *)realloc(nodes, capacity * sizeof(uint32_t));
|
||||
versions = (int64_t *)realloc(versions, capacity * sizeof(int64_t));
|
||||
}
|
||||
|
||||
nodes[end] = node;
|
||||
versions[end] = version;
|
||||
++end;
|
||||
}
|
||||
|
||||
/// Inform that there will be no calls to rootForVersion with a version less
|
||||
/// than `oldestVersion`
|
||||
void setOldestVersion(int64_t oldestVersion) {
|
||||
const uint32_t firstToKeep = lastLeq(oldestVersion);
|
||||
|
||||
if (firstToKeep != 0) {
|
||||
memmove(nodes, nodes + firstToKeep,
|
||||
(end - firstToKeep) * sizeof(uint32_t));
|
||||
memmove(versions, versions + firstToKeep,
|
||||
(end - firstToKeep) * sizeof(int64_t));
|
||||
end -= firstToKeep;
|
||||
}
|
||||
assert(end > 0);
|
||||
assert(versions[0] <= oldestVersion);
|
||||
}
|
||||
|
||||
/// Get a root node that can correctly be used for `version`
|
||||
uint32_t rootForVersion(int64_t version) const {
|
||||
return nodes[lastLeq(version)];
|
||||
}
|
||||
|
||||
const uint32_t *roots() const { return nodes; }
|
||||
int rootCount() const { return end; }
|
||||
|
||||
RootSet() {
|
||||
nodes = (uint32_t *)malloc(kMinCapacity * sizeof(uint32_t));
|
||||
versions = (int64_t *)malloc(kMinCapacity * sizeof(int64_t));
|
||||
capacity = kMinCapacity;
|
||||
nodes[0] = 0;
|
||||
versions[0] = 0;
|
||||
end = 1;
|
||||
}
|
||||
|
||||
~RootSet() {
|
||||
free(versions);
|
||||
free(nodes);
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t lastLeq(int64_t version) const {
|
||||
assert(end > 0);
|
||||
assert(versions[0] <= version);
|
||||
|
||||
// Find the last version <= oldestVersion
|
||||
int left = 1;
|
||||
int right = end - 1;
|
||||
int result = 0;
|
||||
while (left <= right) {
|
||||
int mid = left + (right - left) / 2;
|
||||
if (versions[mid] <= version) {
|
||||
result = mid;
|
||||
left = mid + 1;
|
||||
} else {
|
||||
right = mid - 1;
|
||||
}
|
||||
}
|
||||
assert(result < end);
|
||||
return result;
|
||||
}
|
||||
uint32_t *nodes;
|
||||
// versions[i] is the version of nodes[i]
|
||||
int64_t *versions;
|
||||
|
||||
constexpr static uint32_t kMinCapacity = 16;
|
||||
uint32_t capacity;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
auto operator<=>(const VersionedMap::Mutation &lhs, const Node &rhs) {
|
||||
int cl = std::min(lhs.param1Length, rhs.entry->keyLen);
|
||||
if (cl > 0) {
|
||||
@@ -593,7 +502,8 @@ struct VersionedMap::Impl {
|
||||
}
|
||||
|
||||
void printInOrder(int64_t version) {
|
||||
printInOrderHelper(version, roots.rootForVersion(version));
|
||||
printInOrderHelper(version,
|
||||
roots.getThreadSafeHandle().rootForVersion(version));
|
||||
}
|
||||
|
||||
void printInOrderHelper(int64_t version, uint32_t node) {
|
||||
@@ -675,7 +585,7 @@ int main() {
|
||||
{
|
||||
int i = 0;
|
||||
constexpr int kNumVersions = 1000;
|
||||
weaselab::RootSet roots;
|
||||
RootSet roots;
|
||||
for (; i < kNumVersions; i += 2) {
|
||||
roots.add(i, i);
|
||||
roots.add(i, i + 1);
|
||||
@@ -686,7 +596,8 @@ int main() {
|
||||
++i;
|
||||
});
|
||||
bench.run("roots - rootForVersion", [&]() {
|
||||
bench.doNotOptimizeAway(roots.rootForVersion(i - kNumVersions / 2));
|
||||
bench.doNotOptimizeAway(
|
||||
roots.getThreadSafeHandle().rootForVersion(i - kNumVersions / 2));
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user