diff --git a/ConflictSet.cpp b/ConflictSet.cpp index b39a137..685eb0c 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -295,6 +295,11 @@ struct Node48 : Node { int8_t index[256]; Child children[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); } @@ -423,6 +428,8 @@ inline void Node48::copyChildrenAndKeyFrom(const Node16 &other) { assert(children[i].child->parent == &other); children[i].child->parent = this; reverseIndex[i] = x; + maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max( + maxOfMax[i >> Node48::kMaxOfMaxShift], children[i].childMaxVersion); ++i; } } @@ -440,6 +447,7 @@ inline void Node48::copyChildrenAndKeyFrom(const Node48 &other) { children[i].child->parent = this; } memcpy(reverseIndex, other.reverseIndex, sizeof(reverseIndex)); + memcpy(maxOfMax, other.maxOfMax, sizeof(maxOfMax)); memcpy(partialKey(), &other + 1, partialKeyLen); } @@ -461,6 +469,8 @@ inline void Node48::copyChildrenAndKeyFrom(const Node256 &other) { assert(children[i].child->parent == &other); children[i].child->parent = this; reverseIndex[i] = c; + maxOfMax[i >> Node48::kMaxOfMaxShift] = std::max( + maxOfMax[i >> Node48::kMaxOfMaxShift], children[i].childMaxVersion); ++i; }, 0, 256); @@ -583,7 +593,7 @@ template struct BoundedFreeListAllocator { if constexpr (!std::is_same_v) { memset(result->children, 0, sizeof(result->children)); } - if constexpr (std::is_same_v) { + if constexpr (std::is_same_v || std::is_same_v) { memset(result->maxOfMax, 0, sizeof(result->maxOfMax)); } return result; @@ -1710,18 +1720,16 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, } break; case Type_Node48: { auto *self = static_cast(n); - bool conflict[Node48::kMaxNodes] = {}; - 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]); - } + // Check all pages bool result = true; - for (auto c : conflict) { - result &= !c; + for (int i = 0; i < Node48::kMaxOfMaxTotalPages; ++i) { + 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; } @@ -1745,8 +1753,8 @@ bool checkMaxBetweenExclusive(Node *n, int begin, int end, bool result = true; for (int i = 0; i < Node256::kMaxOfMaxPageSize; ++i) { int j = ((end - 1) & ~(Node256::kMaxOfMaxPageSize - 1)) + i; - result &= !((self->children[j].childMaxVersion > readVersion) & - (begin <= j) & (j < end)); + result &= + !((self->children[j].childMaxVersion > readVersion) & inBounds(j)); } if (!result) { return result; @@ -2686,7 +2694,10 @@ void setMaxVersion(Node *n, ConflictSet::Impl *impl, int64_t newMax) { case Type_Node48: { auto *n48 = static_cast(n); 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; } case Type_Node256: {