Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-06-30 16:58:14 +0300
committerJacques Lucke <jacques@blender.org>2020-06-30 16:58:29 +0300
commit37820651bb4f22e316f00a02e4bf5da2589a03c9 (patch)
treed5a720582e58c151c61a09304f5b354516283899
parent5b03f49302a39577f2373906cfba19feebfaa9ba (diff)
BLI: add Array constructor that does not initialize non-trivial types
This should rarely be necessary, but I have a use case coming up soon.
-rw-r--r--source/blender/blenlib/BLI_array.hh21
-rw-r--r--source/blender/blenlib/BLI_memory_utils.hh7
-rw-r--r--tests/gtests/blenlib/BLI_array_test.cc35
3 files changed, 61 insertions, 2 deletions
diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh
index 07155439170..25267bc65d6 100644
--- a/source/blender/blenlib/BLI_array.hh
+++ b/source/blender/blenlib/BLI_array.hh
@@ -27,8 +27,7 @@
* blender::Array should usually be used instead of blender::Vector whenever the number of elements
* is known at construction time. Note however, that blender::Array will default construct all
* elements when initialized with the size-constructor. For trivial types, this does nothing. In
- * all other cases, this adds overhead. If this becomes a problem, a different constructor which
- * does not do default construction can be added.
+ * all other cases, this adds overhead.
*
* A main benefit of using Array over Vector is that it expresses the intent of the developer
* better. It indicates that the size of the data structure is not expected to change. Furthermore,
@@ -130,6 +129,24 @@ class Array {
uninitialized_fill_n(m_data, m_size, value);
}
+ /**
+ * Create a new array with uninitialized elements. The caller is responsible for constructing the
+ * elements. Moving, copying or destructing an Array with uninitialized elements invokes
+ * undefined behavior.
+ *
+ * This should be used very rarely. Note, that the normal size-constructor also does not
+ * initialize the elements when T is trivially constructible. Therefore, it only makes sense to
+ * use this with non trivially constructible types.
+ *
+ * Usage:
+ * Array<std::string> my_strings(10, NoInitialization());
+ */
+ Array(uint size, NoInitialization)
+ {
+ m_size = size;
+ m_data = this->get_buffer_for_size(size);
+ }
+
Array(const Array &other) : m_allocator(other.m_allocator)
{
m_size = other.size();
diff --git a/source/blender/blenlib/BLI_memory_utils.hh b/source/blender/blenlib/BLI_memory_utils.hh
index baad862bce5..0c2cae6c606 100644
--- a/source/blender/blenlib/BLI_memory_utils.hh
+++ b/source/blender/blenlib/BLI_memory_utils.hh
@@ -242,6 +242,13 @@ template<size_t Size, size_t Alignment> class alignas(Alignment) AlignedBuffer {
}
};
+/**
+ * This can be used by container constructors. A parameter of this type should be used to indicate
+ * that the constructor does not construct the elements.
+ */
+class NoInitialization {
+};
+
} // namespace blender
#endif /* __BLI_MEMORY_UTILS_HH__ */
diff --git a/tests/gtests/blenlib/BLI_array_test.cc b/tests/gtests/blenlib/BLI_array_test.cc
index 9ff4dc9a371..08f61a19900 100644
--- a/tests/gtests/blenlib/BLI_array_test.cc
+++ b/tests/gtests/blenlib/BLI_array_test.cc
@@ -124,3 +124,38 @@ TEST(array, TrivialTypeSizeConstructor)
EXPECT_EQ(*ptr, magic);
delete array;
}
+
+struct ConstructibleType {
+ char value;
+
+ ConstructibleType()
+ {
+ value = 42;
+ }
+};
+
+TEST(array, NoInitializationSizeConstructor)
+{
+ using MyArray = Array<ConstructibleType>;
+
+ AlignedBuffer<sizeof(MyArray), alignof(MyArray)> buffer;
+ char *buffer_ptr = (char *)buffer.ptr();
+ memset(buffer_ptr, 100, sizeof(MyArray));
+
+ /* Doing this to avoid some compiler optimization. */
+ for (uint i : IndexRange(sizeof(MyArray))) {
+ EXPECT_EQ(buffer_ptr[i], 100);
+ }
+
+ {
+ MyArray &array = *new (buffer.ptr()) MyArray(1, NoInitialization());
+ EXPECT_EQ(array[0].value, 100);
+ array.clear_without_destruct();
+ array.~Array();
+ }
+ {
+ MyArray &array = *new (buffer.ptr()) MyArray(1);
+ EXPECT_EQ(array[0].value, 42);
+ array.~Array();
+ }
+}