Commit 299dbc58 by Abseil Team Committed by Copybara-Service

Unify btree EmptyNode allocation code across compilers.

We currently have a workaround for MSVC, which has constexpr pointer arithmetic bugs. The bug seems to still exist and the existing code for non-MSVC compilers doesn't build.

This alternative constexpr constructor avoids pointer arithmetic and seems to be working for all, including MSVC.

PiperOrigin-RevId: 592586957
Change-Id: Ic585693c3a7abaab5fbbc0954b8ee924994f8dbf
parent b559abcb
...@@ -572,13 +572,6 @@ class btree_node { ...@@ -572,13 +572,6 @@ class btree_node {
btree_node(btree_node const &) = delete; btree_node(btree_node const &) = delete;
btree_node &operator=(btree_node const &) = delete; btree_node &operator=(btree_node const &) = delete;
// Public for EmptyNodeType.
constexpr static size_type Alignment() {
static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
"Alignment of all nodes must be equal.");
return InternalLayout().Alignment();
}
protected: protected:
btree_node() = default; btree_node() = default;
...@@ -653,6 +646,12 @@ class btree_node { ...@@ -653,6 +646,12 @@ class btree_node {
return InternalLayout().AllocSize(); return InternalLayout().AllocSize();
} }
constexpr static size_type Alignment() {
static_assert(LeafLayout(1).Alignment() == InternalLayout().Alignment(),
"Alignment of all nodes must be equal.");
return InternalLayout().Alignment();
}
// N is the index of the type in the Layout definition. // N is the index of the type in the Layout definition.
// ElementType<N> is the Nth type in the Layout definition. // ElementType<N> is the Nth type in the Layout definition.
template <size_type N> template <size_type N>
...@@ -1321,7 +1320,7 @@ class btree { ...@@ -1321,7 +1320,7 @@ class btree {
// We use a static empty node for the root/leftmost/rightmost of empty btrees // We use a static empty node for the root/leftmost/rightmost of empty btrees
// in order to avoid branching in begin()/end(). // in order to avoid branching in begin()/end().
struct alignas(node_type::Alignment()) EmptyNodeType : node_type { struct EmptyNodeType : node_type {
using field_type = typename node_type::field_type; using field_type = typename node_type::field_type;
node_type *parent; node_type *parent;
#ifdef ABSL_BTREE_ENABLE_GENERATIONS #ifdef ABSL_BTREE_ENABLE_GENERATIONS
...@@ -1334,25 +1333,12 @@ class btree { ...@@ -1334,25 +1333,12 @@ class btree {
// as a leaf node). max_count() is never called when the tree is empty. // as a leaf node). max_count() is never called when the tree is empty.
field_type max_count = node_type::kInternalNodeMaxCount + 1; field_type max_count = node_type::kInternalNodeMaxCount + 1;
#ifdef _MSC_VER constexpr EmptyNodeType() : parent(this) {}
// MSVC has constexpr code generations bugs here.
EmptyNodeType() : parent(this) {}
#else
explicit constexpr EmptyNodeType(node_type *p) : parent(p) {}
#endif
}; };
static node_type *EmptyNode() { static node_type *EmptyNode() {
#ifdef _MSC_VER alignas(node_type::Alignment()) static constexpr EmptyNodeType empty_node;
static EmptyNodeType *empty_node = new EmptyNodeType;
// This assert fails on some other construction methods.
assert(empty_node->parent == empty_node);
return empty_node;
#else
static constexpr EmptyNodeType empty_node(
const_cast<EmptyNodeType *>(&empty_node));
return const_cast<EmptyNodeType *>(&empty_node); return const_cast<EmptyNodeType *>(&empty_node);
#endif
} }
enum : uint32_t { enum : uint32_t {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment