summaryrefslogtreecommitdiffstats
path: root/vespalib
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahooinc.com>2022-03-28 14:30:33 +0000
committerTor Brede Vekterli <vekterli@yahooinc.com>2022-03-28 14:30:33 +0000
commitd11c7181ef8b80fb20a6b4285da4fe95f577b4ae (patch)
tree549726516e60849d382560ba0db1cd4f4faf6ec7 /vespalib
parent19f950ba81d98904b67fd45c48865754af4b590f (diff)
Let empty entry BufferType sentinel be static instead of global
Avoids issue where a global BufferType with a transitive Alloc instance binds to a null reference allocator since the global allocator instance has not yet been initialized as part of global constructor invocation. Manually hoist empty sentinel ref outside of loops since it might not be obvious to the compiler that the same object is reused over and over.
Diffstat (limited to 'vespalib')
-rw-r--r--vespalib/src/vespa/vespalib/btree/btreenodestore.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_type.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/buffer_type.hpp16
-rw-r--r--vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h2
-rw-r--r--vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp3
5 files changed, 18 insertions, 7 deletions
diff --git a/vespalib/src/vespa/vespalib/btree/btreenodestore.h b/vespalib/src/vespa/vespalib/btree/btreenodestore.h
index 444bf641899..d4a5ae42ef8 100644
--- a/vespalib/src/vespa/vespalib/btree/btreenodestore.h
+++ b/vespalib/src/vespa/vespalib/btree/btreenodestore.h
@@ -25,7 +25,7 @@ template <typename EntryType>
class BTreeNodeBufferType : public datastore::BufferType<EntryType, FrozenBtreeNode<EntryType>>
{
using ParentType = datastore::BufferType<EntryType, FrozenBtreeNode<EntryType>>;
- using ParentType::_emptyEntry;
+ using ParentType::empty_entry;
using ParentType::_arraySize;
using ElemCount = typename ParentType::ElemCount;
using CleanContext = typename ParentType::CleanContext;
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.h b/vespalib/src/vespa/vespalib/datastore/buffer_type.h
index 7d041646ca5..3394af18b04 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_type.h
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.h
@@ -133,7 +133,7 @@ template <typename EntryType, typename EmptyType = EntryType>
class BufferType : public BufferTypeBase
{
protected:
- static EntryType _emptyEntry;
+ static const EntryType& empty_entry() noexcept;
public:
BufferType() noexcept : BufferType(1,1,1) {}
diff --git a/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp b/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
index ae2659ef65b..72c8f574a70 100644
--- a/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/buffer_type.hpp
@@ -51,8 +51,9 @@ void
BufferType<EntryType, EmptyType>::initializeReservedElements(void *buffer, ElemCount reservedElems)
{
EntryType *e = static_cast<EntryType *>(buffer);
+ const auto& empty = empty_entry();
for (size_t j = reservedElems; j != 0; --j) {
- new (static_cast<void *>(e)) EntryType(_emptyEntry);
+ new (static_cast<void *>(e)) EntryType(empty);
++e;
}
}
@@ -62,13 +63,22 @@ void
BufferType<EntryType, EmptyType>::cleanHold(void *buffer, size_t offset, ElemCount numElems, CleanContext)
{
EntryType *e = static_cast<EntryType *>(buffer) + offset;
+ const auto& empty = empty_entry();
for (size_t j = numElems; j != 0; --j) {
- *e = _emptyEntry;
+ *e = empty;
++e;
}
}
template <typename EntryType, typename EmptyType>
-EntryType BufferType<EntryType, EmptyType>::_emptyEntry = EmptyType();
+const EntryType&
+BufferType<EntryType, EmptyType>::empty_entry() noexcept
+{
+ // It's possible for EntryType to wrap e.g. an Alloc instance, which has a transitive
+ // dependency on globally constructed allocator object(s). To avoid issues with global
+ // construction order, initialize the sentinel on the first access.
+ static EntryType empty = EmptyType();
+ return empty;
+}
}
diff --git a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
index 50d15d4a27c..ccaedaa9b64 100644
--- a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
+++ b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.h
@@ -20,7 +20,7 @@ class LargeArrayBufferType : public BufferType<Array<EntryT>>
using AllocSpec = ArrayStoreConfig::AllocSpec;
using ArrayType = Array<EntryT>;
using ParentType = BufferType<ArrayType>;
- using ParentType::_emptyEntry;
+ using ParentType::empty_entry;
using CleanContext = typename ParentType::CleanContext;
std::shared_ptr<alloc::MemoryAllocator> _memory_allocator;
public:
diff --git a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
index aeeef8166c6..3042bbff73f 100644
--- a/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
+++ b/vespalib/src/vespa/vespalib/datastore/large_array_buffer_type.hpp
@@ -22,9 +22,10 @@ void
LargeArrayBufferType<EntryT>::cleanHold(void* buffer, size_t offset, ElemCount numElems, CleanContext cleanCtx)
{
ArrayType* elem = static_cast<ArrayType*>(buffer) + offset;
+ const auto& empty = empty_entry();
for (size_t i = 0; i < numElems; ++i) {
cleanCtx.extraBytesCleaned(sizeof(EntryT) * elem->size());
- *elem = _emptyEntry;
+ *elem = empty;
++elem;
}
}