[Bf-blender-cvs] [4328946e12d] functions: work better with uninitialized memory + tests for SmallVector

Jacques Lucke noreply at git.blender.org
Sun Feb 10 20:25:20 CET 2019


Commit: 4328946e12df9e7a1410b40efc6e668e6914186e
Author: Jacques Lucke
Date:   Thu Jan 24 17:32:32 2019 +0100
Branches: functions
https://developer.blender.org/rB4328946e12df9e7a1410b40efc6e668e6914186e

work better with uninitialized memory + tests for SmallVector

===================================================================

M	source/blender/blenlib/BLI_small_vector.hpp
A	tests/gtests/blenlib/BLI_small_vector_test.cc
M	tests/gtests/blenlib/CMakeLists.txt

===================================================================

diff --git a/source/blender/blenlib/BLI_small_vector.hpp b/source/blender/blenlib/BLI_small_vector.hpp
index 59d309e6a66..28d9af735e0 100644
--- a/source/blender/blenlib/BLI_small_vector.hpp
+++ b/source/blender/blenlib/BLI_small_vector.hpp
@@ -3,6 +3,7 @@
 #include "BLI_utildefines.h"
 #include <cstdlib>
 #include <cstring>
+#include <memory>
 
 namespace BLI {
 
@@ -23,19 +24,12 @@ namespace BLI {
 		}
 
 		SmallVector(uint size)
+			: SmallVector()
 		{
-			if (size > N) {
-				this->m_elements = (T *)std::malloc(sizeof(T) * size);
-				this->m_capacity = size;
-			}
-			else {
-				this->m_elements = this->m_small_buffer;
-				this->m_capacity = N;
-			}
+			this->reserve(size);
 			for (uint i = 0; i < size; i++) {
-				this->m_elements[i] = T();
+				this->append(T());
 			}
-			this->m_size = size;
 		}
 
 		SmallVector(std::initializer_list<T> values)
@@ -144,13 +138,22 @@ namespace BLI {
 			}
 
 			this->m_capacity = min_capacity;
-			uint new_byte_size = sizeof(T) * this->m_capacity;
-			if (this->is_small()) {
-				this->m_elements = (T *)std::malloc(new_byte_size);
+
+			T *new_array = (T *)std::malloc(sizeof(T) * this->m_capacity);
+			std::uninitialized_copy(
+				std::make_move_iterator(this->begin()),
+				std::make_move_iterator(this->end()),
+				new_array);
+
+			for (uint i = 0; i < this->m_size; i++) {
+				(this->m_elements + i)->~T();
 			}
-			else {
-				this->m_elements = (T *)std::realloc(this->m_elements, new_byte_size);
+
+			if (!this->is_small()) {
+				std::free(this->m_elements);
 			}
+
+			this->m_elements = new_array;
 		}
 
 		void free_own_buffer()
@@ -167,11 +170,11 @@ namespace BLI {
 		{
 			if (other.is_small()) {
 				this->m_elements = this->m_small_buffer;
-				std::memcpy(this->m_small_buffer, other.m_small_buffer, sizeof(T) * other.m_size);
+				std::copy(other.begin(), other.end(), this->m_elements);
 			}
 			else {
 				this->m_elements = (T *)std::malloc(sizeof(T) * other.m_capacity);
-				std::memcpy(this->m_elements, other.m_elements, other.m_size);
+				std::uninitialized_copy(other.begin(), other.end(), this->m_elements);
 			}
 
 			this->m_capacity = other.m_capacity;
@@ -181,8 +184,11 @@ namespace BLI {
 		void steal_from_other(SmallVector &&other)
 		{
 			if (other.is_small()) {
+				std::copy(
+					std::make_move_iterator(other.begin()),
+					std::make_move_iterator(other.end()),
+					this->m_small_buffer);
 				this->m_elements = this->m_small_buffer;
-				std::memcpy(this->m_small_buffer, other.m_small_buffer, sizeof(T) * other.m_size);
 			}
 			else {
 				this->m_elements = other.m_elements;
diff --git a/tests/gtests/blenlib/BLI_small_vector_test.cc b/tests/gtests/blenlib/BLI_small_vector_test.cc
new file mode 100644
index 00000000000..13499be7e67
--- /dev/null
+++ b/tests/gtests/blenlib/BLI_small_vector_test.cc
@@ -0,0 +1,144 @@
+#include "testing/testing.h"
+#include "BLI_small_vector.hpp"
+
+using IntVector = BLI::SmallVector<int>;
+
+TEST(small_vector, DefaultConstructor)
+{
+	IntVector vec;
+	EXPECT_EQ(vec.size(), 0);
+}
+
+TEST(small_vector, SizeConstructor)
+{
+	IntVector vec(3);
+	EXPECT_EQ(vec.size(), 3);
+	EXPECT_EQ(vec[0], 0);
+	EXPECT_EQ(vec[1], 0);
+	EXPECT_EQ(vec[2], 0);
+}
+
+TEST(small_vector, InitializerListConstructor)
+{
+	IntVector vec = {1, 3, 4, 6};
+	EXPECT_EQ(vec.size(), 4);
+	EXPECT_EQ(vec[0], 1);
+	EXPECT_EQ(vec[1], 3);
+	EXPECT_EQ(vec[2], 4);
+	EXPECT_EQ(vec[3], 6);
+}
+
+TEST(small_vector, CopyConstructor)
+{
+	IntVector vec1 = {1, 2, 3};
+	IntVector vec2(vec1);
+	EXPECT_EQ(vec2.size(), 3);
+	EXPECT_EQ(vec2[0], 1);
+	EXPECT_EQ(vec2[1], 2);
+	EXPECT_EQ(vec2[2], 3);
+
+	vec1[1] = 5;
+	EXPECT_EQ(vec1[1], 5);
+	EXPECT_EQ(vec2[1], 2);
+}
+
+TEST(small_vector, MoveAssignment)
+{
+	IntVector vec = {1, 2};
+	EXPECT_EQ(vec.size(), 2);
+	EXPECT_EQ(vec[0], 1);
+	EXPECT_EQ(vec[1], 2);
+
+	vec = IntVector({5});
+	EXPECT_EQ(vec.size(), 1);
+	EXPECT_EQ(vec[0], 5);
+}
+
+TEST(small_vector, CopyAssignment)
+{
+	IntVector vec1 = {1, 2, 3};
+	IntVector vec2 = {4, 5};
+	EXPECT_EQ(vec1.size(), 3);
+	EXPECT_EQ(vec2.size(), 2);
+
+	vec2 = vec1;
+	EXPECT_EQ(vec2.size(), 3);
+
+	vec1[0] = 7;
+	EXPECT_EQ(vec1[0], 7);
+	EXPECT_EQ(vec2[0], 1);
+}
+
+TEST(small_vector, Append)
+{
+	IntVector vec;
+	vec.append(3);
+	vec.append(6);
+	vec.append(7);
+	EXPECT_EQ(vec.size(), 3);
+	EXPECT_EQ(vec[0], 3);
+	EXPECT_EQ(vec[1], 6);
+	EXPECT_EQ(vec[2], 7);
+}
+
+TEST(small_vector, Fill)
+{
+	IntVector vec(5);
+	vec.fill(3);
+	EXPECT_EQ(vec.size(), 5);
+	EXPECT_EQ(vec[0], 3);
+	EXPECT_EQ(vec[1], 3);
+	EXPECT_EQ(vec[2], 3);
+	EXPECT_EQ(vec[3], 3);
+	EXPECT_EQ(vec[4], 3);
+}
+
+TEST(small_vector, Iterator)
+{
+	IntVector vec({1, 4, 9, 16});
+	int i = 1;
+	for (int value : vec) {
+		EXPECT_EQ(value, i * i);
+		i++;
+	}
+}
+
+TEST(small_Vector, BecomeLarge)
+{
+	BLI::SmallVector<int, 4> vec;
+	for (int i = 0; i < 100; i++) {
+		vec.append(i * 5);
+	}
+	EXPECT_EQ(vec.size(), 100);
+	for (int i = 0; i < 100; i++) {
+		EXPECT_EQ(vec[i], i * 5);
+	}
+}
+
+IntVector return_by_value_helper()
+{
+	return IntVector({3, 5, 1});
+}
+
+TEST(small_vector, ReturnByValue)
+{
+	IntVector vec = return_by_value_helper();
+	EXPECT_EQ(vec.size(), 3);
+	EXPECT_EQ(vec[0], 3);
+	EXPECT_EQ(vec[1], 5);
+	EXPECT_EQ(vec[2], 1);
+}
+
+TEST(small_vector, VectorOfVectors_Append)
+{
+	BLI::SmallVector<IntVector> vec;
+	EXPECT_EQ(vec.size(), 0);
+
+	vec.append({1, 2});
+	vec.append({7, 8});
+	EXPECT_EQ(vec.size(), 2);
+	EXPECT_EQ(vec[0][0], 1);
+	EXPECT_EQ(vec[0][1], 2);
+	EXPECT_EQ(vec[1][0], 7);
+	EXPECT_EQ(vec[1][1], 8);
+}
\ No newline at end of file
diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt
index e837f703423..4da1a42d7ec 100644
--- a/tests/gtests/blenlib/CMakeLists.txt
+++ b/tests/gtests/blenlib/CMakeLists.txt
@@ -55,6 +55,7 @@ BLENDER_TEST(BLI_math_geom "bf_blenlib")
 BLENDER_TEST(BLI_memiter "bf_blenlib")
 BLENDER_TEST(BLI_path_util "${BLI_path_util_extra_libs}")
 BLENDER_TEST(BLI_polyfill_2d "bf_blenlib")
+BLENDER_TEST(BLI_small_vector "bf_blenlib")
 BLENDER_TEST(BLI_stack "bf_blenlib")
 BLENDER_TEST(BLI_string "bf_blenlib")
 BLENDER_TEST(BLI_string_utf8 "bf_blenlib")



More information about the Bf-blender-cvs mailing list