"max of max" for Node48 again, but physical instead of logical
This commit is contained in:
@@ -295,6 +295,11 @@ struct Node48 : Node {
|
|||||||
int8_t index[256];
|
int8_t index[256];
|
||||||
Child children[kMaxNodes];
|
Child children[kMaxNodes];
|
||||||
uint8_t reverseIndex[kMaxNodes];
|
uint8_t reverseIndex[kMaxNodes];
|
||||||
|
constexpr static int kMaxOfMaxPageSize = 8;
|
||||||
|
constexpr static int kMaxOfMaxShift =
|
||||||
|
std::countr_zero(uint32_t(kMaxOfMaxPageSize));
|
||||||
|
constexpr static int kMaxOfMaxTotalPages = kMaxNodes / kMaxOfMaxPageSize;
|
||||||
|
int64_t maxOfMax[kMaxOfMaxTotalPages];
|
||||||
|
|
||||||
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
||||||
|
|
||||||
@@ -423,6 +428,8 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) {
|
|||||||
assert(children[i].child->parent == &other);
|
assert(children[i].child->parent == &other);
|
||||||
children[i].child->parent = this;
|
children[i].child->parent = this;
|
||||||
reverseIndex[i] = x;
|
reverseIndex[i] = x;
|
||||||
|
maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max(
|
||||||
|
maxOfMax[i >> Node48::kMaxOfMaxShift], children[i].childMaxVersion);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,6 +447,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node48 &other) {
|
|||||||
children[i].child->parent = this;
|
children[i].child->parent = this;
|
||||||
}
|
}
|
||||||
memcpy(reverseIndex, other.reverseIndex, sizeof(reverseIndex));
|
memcpy(reverseIndex, other.reverseIndex, sizeof(reverseIndex));
|
||||||
|
memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax));
|
||||||
memcpy(partialKey(), &other + 1, partialKeyLen);
|
memcpy(partialKey(), &other + 1, partialKeyLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -461,6 +469,8 @@ inline void Node48::copyChildrenAndKeyFrom(const Node256 &other) {
|
|||||||
assert(children[i].child->parent == &other);
|
assert(children[i].child->parent == &other);
|
||||||
children[i].child->parent = this;
|
children[i].child->parent = this;
|
||||||
reverseIndex[i] = c;
|
reverseIndex[i] = c;
|
||||||
|
maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max(
|
||||||
|
maxOfMax[i >> Node48::kMaxOfMaxShift], children[i].childMaxVersion);
|
||||||
++i;
|
++i;
|
||||||
},
|
},
|
||||||
0, 256);
|
0, 256);
|
||||||
@@ -583,7 +593,7 @@ template <class T> struct BoundedFreeListAllocator {
|
|||||||
if constexpr (!std::is_same_v<T, Node0>) {
|
if constexpr (!std::is_same_v<T, Node0>) {
|
||||||
memset(result->children, 0, sizeof(result->children));
|
memset(result->children, 0, sizeof(result->children));
|
||||||
}
|
}
|
||||||
if constexpr (std::is_same_v<T, Node256>) {
|
if constexpr (std::is_same_v<T, Node48> || std::is_same_v<T, Node256>) {
|
||||||
memset(result->maxOfMax, 0, sizeof(result->maxOfMax));
|
memset(result->maxOfMax, 0, sizeof(result->maxOfMax));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -1710,18 +1720,16 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end,
|
|||||||
} break;
|
} break;
|
||||||
case Type_Node48: {
|
case Type_Node48: {
|
||||||
auto *self = static_cast<Node48 *>(n);
|
auto *self = static_cast<Node48 *>(n);
|
||||||
bool conflict[Node48::kMaxNodes] = {};
|
// Check all pages
|
||||||
assume(self->numChildren >= kMinChildrenNode48 - 1 /* entry present */);
|
|
||||||
assume(self->numChildren <= Node48::kMaxNodes);
|
|
||||||
for (int i = 0; i < Node48::kMaxNodes; ++i) {
|
|
||||||
assert(i >= self->numChildren || self->index[self->reverseIndex[i]] == i);
|
|
||||||
assert(i < self->numChildren || self->children[i].childMaxVersion == 0);
|
|
||||||
conflict[i] = (self->children[i].childMaxVersion > readVersion) &
|
|
||||||
inBounds(self->reverseIndex[i]);
|
|
||||||
}
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
for (auto c : conflict) {
|
for (int i = 0; i < Node48::kMaxOfMaxTotalPages; ++i) {
|
||||||
result &= !c;
|
if (self->maxOfMax[i] > readVersion) {
|
||||||
|
for (int j = 0; j < Node48::kMaxOfMaxPageSize; ++j) {
|
||||||
|
int k = (i << Node48::kMaxOfMaxShift) + j;
|
||||||
|
result &= !(self->children[k].childMaxVersion > readVersion &&
|
||||||
|
inBounds(self->reverseIndex[k]));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -1745,8 +1753,8 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end,
|
|||||||
bool result = true;
|
bool result = true;
|
||||||
for (int i = 0; i < Node256::kMaxOfMaxPageSize; ++i) {
|
for (int i = 0; i < Node256::kMaxOfMaxPageSize; ++i) {
|
||||||
int j = ((end - 1) & ~(Node256::kMaxOfMaxPageSize - 1)) + i;
|
int j = ((end - 1) & ~(Node256::kMaxOfMaxPageSize - 1)) + i;
|
||||||
result &= !((self->children[j].childMaxVersion > readVersion) &
|
result &=
|
||||||
(begin <= j) & (j < end));
|
!((self->children[j].childMaxVersion > readVersion) & inBounds(j));
|
||||||
}
|
}
|
||||||
if (!result) {
|
if (!result) {
|
||||||
return result;
|
return result;
|
||||||
@@ -2686,7 +2694,10 @@ void setMaxVersion(Node *n, ConflictSet::Impl *impl, int64_t newMax) {
|
|||||||
case Type_Node48: {
|
case Type_Node48: {
|
||||||
auto *n48 = static_cast<Node48 *>(n);
|
auto *n48 = static_cast<Node48 *>(n);
|
||||||
assert(n48->bitSet.test(index));
|
assert(n48->bitSet.test(index));
|
||||||
n48->children[n48->index[index]].childMaxVersion = newMax;
|
int i = n48->index[index];
|
||||||
|
n48->children[i].childMaxVersion = newMax;
|
||||||
|
n48->maxOfMax[i >> Node48::kMaxOfMaxShift] =
|
||||||
|
std::max(n48->maxOfMax[i >> Node48::kMaxOfMaxShift], newMax);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case Type_Node256: {
|
case Type_Node256: {
|
||||||
|
Reference in New Issue
Block a user