Compare commits
2 Commits
26bd8b94cc
...
a9caa0249e
Author | SHA1 | Date | |
---|---|---|---|
a9caa0249e | |||
08b2b7f41a |
157
ConflictSet.cpp
157
ConflictSet.cpp
@@ -174,12 +174,12 @@ int BitSet::firstSetGeq(int i) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum class Type : int8_t {
|
||||
Node0,
|
||||
Node3,
|
||||
Node16,
|
||||
Node48,
|
||||
Node256,
|
||||
enum Type {
|
||||
Type_Node0,
|
||||
Type_Node3,
|
||||
Type_Node16,
|
||||
Type_Node48,
|
||||
Type_Node256,
|
||||
};
|
||||
|
||||
struct Node {
|
||||
@@ -211,24 +211,25 @@ struct Child {
|
||||
};
|
||||
|
||||
struct Node0 : Node {
|
||||
Node0() { this->type = Type::Node0; }
|
||||
Node0() { this->type = Type_Node0; }
|
||||
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
||||
};
|
||||
|
||||
struct Node3 : Node {
|
||||
constexpr static auto kMaxNodes = 3;
|
||||
// Sorted
|
||||
uint8_t index[kMaxNodes];
|
||||
Child children[kMaxNodes];
|
||||
Node3() { this->type = Type::Node3; }
|
||||
Node3() { this->type = Type_Node3; }
|
||||
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
||||
};
|
||||
|
||||
struct Node16 : Node {
|
||||
// Sorted
|
||||
constexpr static auto kMaxNodes = 16;
|
||||
// Sorted
|
||||
uint8_t index[kMaxNodes];
|
||||
Child children[kMaxNodes];
|
||||
Node16() { this->type = Type::Node16; }
|
||||
Node16() { this->type = Type_Node16; }
|
||||
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
||||
};
|
||||
|
||||
@@ -239,7 +240,7 @@ struct Node48 : Node {
|
||||
int8_t index[256];
|
||||
Node48() {
|
||||
memset(index, -1, 256);
|
||||
this->type = Type::Node48;
|
||||
this->type = Type_Node48;
|
||||
}
|
||||
uint8_t *partialKey() { return (uint8_t *)(this + 1); }
|
||||
};
|
||||
@@ -248,7 +249,7 @@ struct Node256 : Node {
|
||||
BitSet bitSet;
|
||||
Child children[256];
|
||||
Node256() {
|
||||
this->type = Type::Node256;
|
||||
this->type = Type_Node256;
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
children[i].child = nullptr;
|
||||
}
|
||||
@@ -365,15 +366,15 @@ private:
|
||||
|
||||
uint8_t *Node::partialKey() {
|
||||
switch (type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
return ((Node0 *)this)->partialKey();
|
||||
case Type::Node3:
|
||||
case Type_Node3:
|
||||
return ((Node3 *)this)->partialKey();
|
||||
case Type::Node16:
|
||||
case Type_Node16:
|
||||
return ((Node16 *)this)->partialKey();
|
||||
case Type::Node48:
|
||||
case Type_Node48:
|
||||
return ((Node48 *)this)->partialKey();
|
||||
case Type::Node256:
|
||||
case Type_Node256:
|
||||
return ((Node256 *)this)->partialKey();
|
||||
}
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
@@ -451,22 +452,22 @@ template <class NodeT> int getNodeIndex(NodeT *self, uint8_t index) {
|
||||
// Precondition - an entry for index must exist in the node
|
||||
Node *&getChildExists(Node *self, uint8_t index) {
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self3 = static_cast<Node3 *>(self);
|
||||
return self3->children[getNodeIndex(self3, index)].child;
|
||||
}
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
return self16->children[getNodeIndex(self16, index)].child;
|
||||
}
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
assert(self48->bitSet.test(index));
|
||||
return self48->children[self48->index[index]].child;
|
||||
}
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *self256 = static_cast<Node256 *>(self);
|
||||
assert(self256->bitSet.test(index));
|
||||
return self256->children[index].child;
|
||||
@@ -481,24 +482,24 @@ Node *&getInTree(Node *n, ConflictSet::Impl *);
|
||||
|
||||
Node *getChild(Node *self, uint8_t index) {
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
return nullptr;
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self3 = static_cast<Node3 *>(self);
|
||||
int i = getNodeIndex(self3, index);
|
||||
return i < 0 ? nullptr : self3->children[i].child;
|
||||
}
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
int i = getNodeIndex(self16, index);
|
||||
return i < 0 ? nullptr : self16->children[i].child;
|
||||
}
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
int i = self48->index[index];
|
||||
return i < 0 ? nullptr : self48->children[i].child;
|
||||
}
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *self256 = static_cast<Node256 *>(self);
|
||||
return self256->children[index].child;
|
||||
}
|
||||
@@ -568,15 +569,15 @@ int getChildGeq(Node *self, int child) {
|
||||
return -1;
|
||||
}
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
return -1;
|
||||
case Type::Node3:
|
||||
case Type_Node3:
|
||||
return getChildGeqSimd(static_cast<Node3 *>(self), child);
|
||||
case Type::Node16:
|
||||
case Type_Node16:
|
||||
return getChildGeqSimd(static_cast<Node16 *>(self), child);
|
||||
case Type::Node48:
|
||||
case Type_Node48:
|
||||
[[fallthrough]];
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
static_assert(offsetof(Node48, bitSet) == offsetof(Node256, bitSet));
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
return self48->bitSet.firstSetGeq(child);
|
||||
@@ -613,30 +614,30 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
|
||||
// Fast path for if it exists already
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
break;
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self3 = static_cast<Node3 *>(self);
|
||||
int i = getNodeIndex(self3, index);
|
||||
if (i >= 0) {
|
||||
return self3->children[i].child;
|
||||
}
|
||||
} break;
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
int i = getNodeIndex(self16, index);
|
||||
if (i >= 0) {
|
||||
return self16->children[i].child;
|
||||
}
|
||||
} break;
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
int secondIndex = self48->index[index];
|
||||
if (secondIndex >= 0) {
|
||||
return self48->children[secondIndex].child;
|
||||
}
|
||||
} break;
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *self256 = static_cast<Node256 *>(self);
|
||||
if (auto &result = self256->children[index].child; result != nullptr) {
|
||||
return result;
|
||||
@@ -645,7 +646,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
}
|
||||
|
||||
switch (self->type) {
|
||||
case Type::Node0: {
|
||||
case Type_Node0: {
|
||||
auto *self0 = static_cast<Node0 *>(self);
|
||||
|
||||
auto *newSelf = allocators->node3.allocate(self->partialKeyLen);
|
||||
@@ -657,7 +658,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
|
||||
goto insert3;
|
||||
}
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
if (self->numChildren == Node3::kMaxNodes) {
|
||||
auto *self3 = static_cast<Node3 *>(self);
|
||||
auto *newSelf = allocators->node16.allocate(self->partialKeyLen);
|
||||
@@ -693,7 +694,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
result = nullptr;
|
||||
return result;
|
||||
}
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
if (self->numChildren == Node16::kMaxNodes) {
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
auto *newSelf = allocators->node48.allocate(self->partialKeyLen);
|
||||
@@ -717,7 +718,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
|
||||
insert16:
|
||||
auto *self16 = static_cast<Node16 *>(self);
|
||||
assert(self->type == Type::Node16);
|
||||
assert(self->type == Type_Node16);
|
||||
|
||||
++self->numChildren;
|
||||
int i = 0;
|
||||
@@ -735,7 +736,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
result = nullptr;
|
||||
return result;
|
||||
}
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
|
||||
if (self->numChildren == 48) {
|
||||
auto *self48 = static_cast<Node48 *>(self);
|
||||
@@ -766,7 +767,7 @@ Node *&getOrCreateChild(Node *&self, uint8_t index,
|
||||
result = nullptr;
|
||||
return result;
|
||||
}
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
insert256:
|
||||
auto *self256 = static_cast<Node256 *>(self);
|
||||
++self->numChildren;
|
||||
@@ -804,7 +805,7 @@ template <bool kUseFreeList>
|
||||
void makeCapacityAtLeast(Node *&self, int capacity, NodeAllocators *allocators,
|
||||
ConflictSet::Impl *impl) {
|
||||
switch (self->type) {
|
||||
case Type::Node0: {
|
||||
case Type_Node0: {
|
||||
auto *self0 = (Node0 *)self;
|
||||
auto *newSelf = allocators->node0.allocate(capacity);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
@@ -818,7 +819,7 @@ void makeCapacityAtLeast(Node *&self, int capacity, NodeAllocators *allocators,
|
||||
}
|
||||
self = newSelf;
|
||||
} break;
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self3 = (Node3 *)self;
|
||||
auto *newSelf = allocators->node3.allocate(capacity);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
@@ -838,7 +839,7 @@ void makeCapacityAtLeast(Node *&self, int capacity, NodeAllocators *allocators,
|
||||
}
|
||||
self = newSelf;
|
||||
} break;
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *self16 = (Node16 *)self;
|
||||
auto *newSelf = allocators->node16.allocate(capacity);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
@@ -858,7 +859,7 @@ void makeCapacityAtLeast(Node *&self, int capacity, NodeAllocators *allocators,
|
||||
}
|
||||
self = newSelf;
|
||||
} break;
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *self48 = (Node48 *)self;
|
||||
auto *newSelf = allocators->node48.allocate(capacity);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
@@ -882,7 +883,7 @@ void makeCapacityAtLeast(Node *&self, int capacity, NodeAllocators *allocators,
|
||||
}
|
||||
self = newSelf;
|
||||
} break;
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *self256 = (Node256 *)self;
|
||||
auto *newSelf = allocators->node256.allocate(capacity);
|
||||
memcpy((char *)newSelf + kNodeCopyBegin, (char *)self + kNodeCopyBegin,
|
||||
@@ -926,9 +927,9 @@ void maybeDownsize(Node *self, NodeAllocators *allocators,
|
||||
#endif
|
||||
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self3 = (Node3 *)self;
|
||||
if (self->numChildren == 0) {
|
||||
auto *newSelf = allocators->node0.allocate(self->partialKeyLen);
|
||||
@@ -980,7 +981,7 @@ void maybeDownsize(Node *self, NodeAllocators *allocators,
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Type::Node16:
|
||||
case Type_Node16:
|
||||
if (self->numChildren + int(self->entryPresent) < kMinChildrenNode16) {
|
||||
auto *self16 = (Node16 *)self;
|
||||
auto *newSelf = allocators->node3.allocate(self->partialKeyLen);
|
||||
@@ -997,7 +998,7 @@ void maybeDownsize(Node *self, NodeAllocators *allocators,
|
||||
allocators->node16.release(self16);
|
||||
}
|
||||
break;
|
||||
case Type::Node48:
|
||||
case Type_Node48:
|
||||
if (self->numChildren + int(self->entryPresent) < kMinChildrenNode48) {
|
||||
auto *self48 = (Node48 *)self;
|
||||
auto *newSelf = allocators->node16.allocate(self->partialKeyLen);
|
||||
@@ -1024,7 +1025,7 @@ void maybeDownsize(Node *self, NodeAllocators *allocators,
|
||||
allocators->node48.release(self48);
|
||||
}
|
||||
break;
|
||||
case Type::Node256:
|
||||
case Type_Node256:
|
||||
if (self->numChildren + int(self->entryPresent) < kMinChildrenNode256) {
|
||||
auto *self256 = (Node256 *)self;
|
||||
auto *newSelf = allocators->node48.allocate(self->partialKeyLen);
|
||||
@@ -1076,27 +1077,27 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl,
|
||||
}
|
||||
|
||||
switch (self->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
allocators->node0.release((Node0 *)self);
|
||||
break;
|
||||
case Type::Node3:
|
||||
case Type_Node3:
|
||||
allocators->node3.release((Node3 *)self);
|
||||
break;
|
||||
case Type::Node16:
|
||||
case Type_Node16:
|
||||
allocators->node16.release((Node16 *)self);
|
||||
break;
|
||||
case Type::Node48:
|
||||
case Type_Node48:
|
||||
allocators->node48.release((Node48 *)self);
|
||||
break;
|
||||
case Type::Node256:
|
||||
case Type_Node256:
|
||||
allocators->node256.release((Node256 *)self);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (parent->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *parent3 = static_cast<Node3 *>(parent);
|
||||
int nodeIndex = getNodeIndex(parent3, parentsIndex);
|
||||
assert(nodeIndex >= 0);
|
||||
@@ -1107,7 +1108,7 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl,
|
||||
sizeof(parent3->children[0]) *
|
||||
(parent->numChildren - (nodeIndex + 1)));
|
||||
} break;
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *parent16 = static_cast<Node16 *>(parent);
|
||||
int nodeIndex = getNodeIndex(parent16, parentsIndex);
|
||||
assert(nodeIndex >= 0);
|
||||
@@ -1118,7 +1119,7 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl,
|
||||
sizeof(parent16->children[0]) *
|
||||
(parent->numChildren - (nodeIndex + 1)));
|
||||
} break;
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *parent48 = static_cast<Node48 *>(parent);
|
||||
parent48->bitSet.reset(parentsIndex);
|
||||
int8_t toRemoveChildrenIndex =
|
||||
@@ -1133,7 +1134,7 @@ Node *erase(Node *self, NodeAllocators *allocators, ConflictSet::Impl *impl,
|
||||
.child->parentsIndex] = toRemoveChildrenIndex;
|
||||
}
|
||||
} break;
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *parent256 = static_cast<Node256 *>(parent);
|
||||
parent256->bitSet.reset(parentsIndex);
|
||||
parent256->children[parentsIndex].child = nullptr;
|
||||
@@ -1450,10 +1451,10 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
||||
}
|
||||
}
|
||||
switch (n->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
// We would have returned above, after not finding a child
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *self = static_cast<Node3 *>(n);
|
||||
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
||||
if (begin <= self->index[i]) {
|
||||
@@ -1461,7 +1462,7 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *self = static_cast<Node16 *>(n);
|
||||
for (int i = 0; i < self->numChildren && self->index[i] < end; ++i) {
|
||||
if (begin <= self->index[i]) {
|
||||
@@ -1469,7 +1470,7 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *self = static_cast<Node48 *>(n);
|
||||
self->bitSet.forEachInRange(
|
||||
[&](int i) {
|
||||
@@ -1479,7 +1480,7 @@ int64_t maxBetweenExclusive(Node *n, int begin, int end) {
|
||||
begin, end);
|
||||
break;
|
||||
}
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *self = static_cast<Node256 *>(n);
|
||||
self->bitSet.forEachInRange(
|
||||
[&](int i) {
|
||||
@@ -2318,24 +2319,24 @@ int64_t &maxVersion(Node *n, ConflictSet::Impl *impl) {
|
||||
return impl->rootMaxVersion;
|
||||
}
|
||||
switch (n->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
__builtin_unreachable(); // GCOVR_EXCL_LINE
|
||||
case Type::Node3: {
|
||||
case Type_Node3: {
|
||||
auto *n3 = static_cast<Node3 *>(n);
|
||||
int i = getNodeIndex(n3, index);
|
||||
return n3->children[i].childMaxVersion;
|
||||
}
|
||||
case Type::Node16: {
|
||||
case Type_Node16: {
|
||||
auto *n16 = static_cast<Node16 *>(n);
|
||||
int i = getNodeIndex(n16, index);
|
||||
return n16->children[i].childMaxVersion;
|
||||
}
|
||||
case Type::Node48: {
|
||||
case Type_Node48: {
|
||||
auto *n48 = static_cast<Node48 *>(n);
|
||||
assert(n48->bitSet.test(index));
|
||||
return n48->children[n48->index[index]].childMaxVersion;
|
||||
}
|
||||
case Type::Node256: {
|
||||
case Type_Node256: {
|
||||
auto *n256 = static_cast<Node256 *>(n);
|
||||
assert(n256->bitSet.test(index));
|
||||
return n256->children[index].childMaxVersion;
|
||||
@@ -2595,19 +2596,19 @@ Iterator firstGeq(Node *n, std::string_view key) {
|
||||
[[maybe_unused]] void checkMemoryBoundInvariants(Node *node, bool &success) {
|
||||
int minNumChildren;
|
||||
switch (node->type) {
|
||||
case Type::Node0:
|
||||
case Type_Node0:
|
||||
minNumChildren = 0;
|
||||
break;
|
||||
case Type::Node3:
|
||||
case Type_Node3:
|
||||
minNumChildren = kMinChildrenNode3;
|
||||
break;
|
||||
case Type::Node16:
|
||||
case Type_Node16:
|
||||
minNumChildren = kMinChildrenNode16;
|
||||
break;
|
||||
case Type::Node48:
|
||||
case Type_Node48:
|
||||
minNumChildren = kMinChildrenNode48;
|
||||
break;
|
||||
case Type::Node256:
|
||||
case Type_Node256:
|
||||
minNumChildren = kMinChildrenNode256;
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user