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-08-24 18:24:13 +0300
committerJacques Lucke <jacques@blender.org>2020-08-24 18:24:13 +0300
commit8e18a9984505514a229d66b38fff31d930367968 (patch)
tree97bb3e6f766e997df712bf081e05e027648e2c28 /source/blender/blenlib/BLI_array.hh
parent530350935472970dccc211b0e728e2db4fd1d8ef (diff)
BLI: improve exception safety of Set and Map
For more information see rB2aff45146f1464ba8899368ad004522cb6a1a98c.
Diffstat (limited to 'source/blender/blenlib/BLI_array.hh')
-rw-r--r--source/blender/blenlib/BLI_array.hh43
1 files changed, 37 insertions, 6 deletions
diff --git a/source/blender/blenlib/BLI_array.hh b/source/blender/blenlib/BLI_array.hh
index d6b7ab03203..dddf4f64ff5 100644
--- a/source/blender/blenlib/BLI_array.hh
+++ b/source/blender/blenlib/BLI_array.hh
@@ -168,7 +168,7 @@ class Array {
Array(Array &&other) noexcept(std::is_nothrow_move_constructible_v<T>)
: Array(NoExceptConstructor(), other.allocator_)
{
- if (other.uses_inline_buffer()) {
+ if (other.data_ == other.inline_buffer_) {
uninitialized_relocate_n(other.data_, other.size_, data_);
}
else {
@@ -183,9 +183,7 @@ class Array {
~Array()
{
destruct_n(data_, size_);
- if (!this->uses_inline_buffer()) {
- allocator_.deallocate(static_cast<void *>(data_));
- }
+ this->deallocate_if_not_inline(data_);
}
Array &operator=(const Array &other)
@@ -365,6 +363,37 @@ class Array {
return InlineBufferCapacity;
}
+ /**
+ * Destruct values and create a new array of the given size. The values in the new array are
+ * default constructed.
+ */
+ void reinitialize(const int64_t new_size)
+ {
+ BLI_assert(new_size >= 0);
+ int64_t old_size = size_;
+
+ destruct_n(data_, size_);
+ size_ = 0;
+
+ if (new_size <= old_size) {
+ default_construct_n(data_, new_size);
+ }
+ else {
+ T *new_data = this->get_buffer_for_size(new_size);
+ try {
+ default_construct_n(new_data, new_size);
+ }
+ catch (...) {
+ this->deallocate_if_not_inline(new_data);
+ throw;
+ }
+ this->deallocate_if_not_inline(data_);
+ data_ = new_data;
+ }
+
+ size_ = new_size;
+ }
+
private:
T *get_buffer_for_size(int64_t size)
{
@@ -382,9 +411,11 @@ class Array {
allocator_.allocate(static_cast<size_t>(size) * sizeof(T), alignof(T), AT));
}
- bool uses_inline_buffer() const
+ void deallocate_if_not_inline(T *ptr)
{
- return data_ == inline_buffer_;
+ if (ptr != inline_buffer_) {
+ allocator_.deallocate(ptr);
+ }
}
};