[Bf-blender-cvs] [4022d8784c3] functions: New list implementation

Jacques Lucke noreply at git.blender.org
Tue Aug 6 12:11:44 CEST 2019


Commit: 4022d8784c305b57d75bafdb35535f02960dc6d1
Author: Jacques Lucke
Date:   Tue Aug 6 11:54:49 2019 +0200
Branches: functions
https://developer.blender.org/rB4022d8784c305b57d75bafdb35535f02960dc6d1

New list implementation

Instead of using a templated list, it is easier to use a "generic" list, that can
handle every type with a CPPTypeInfo extension. This simplifies the code quite
a bit, because templates can be avoided in many places.
This also makes it easier to add new types.

The list will still be refcounted and still have the shared immutability semantic.
So when a list has more than one user, it is immutable.

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

R080	source/blender/blenlib/BLI_shared.hpp	source/blender/blenlib/BLI_refcount.hpp
D	source/blender/blenlib/BLI_shared_immutable.hpp
M	source/blender/blenlib/CMakeLists.txt
M	source/blender/functions/CMakeLists.txt
M	source/blender/functions/FN_tuple.hpp
M	source/blender/functions/FN_types.hpp
M	source/blender/functions/backends/tuple/cpp_type_info.hpp
A	source/blender/functions/backends/tuple/list.cpp
A	source/blender/functions/backends/tuple/list.hpp
M	source/blender/functions/backends/tuple/tuple-c.cpp
M	source/blender/functions/backends/tuple/tuple-c.h
M	source/blender/functions/backends/tuple/tuple.hpp
M	source/blender/functions/core/core-c.cpp
M	source/blender/functions/core/core-c.h
M	source/blender/functions/core/data_graph.hpp
M	source/blender/functions/core/function.hpp
M	source/blender/functions/core/type.hpp
M	source/blender/functions/frontends/data_flow_nodes/mappings/socket_loaders.cpp
M	source/blender/functions/functions/auto_vectorization.cpp
M	source/blender/functions/functions/lists.cpp
M	source/blender/functions/functions/lists.hpp
M	source/blender/functions/functions/object_input.cpp
M	source/blender/functions/functions/ranges.cpp
A	source/blender/functions/types/lists.cpp
M	source/blender/functions/types/lists.hpp
D	source/blender/functions/types/numeric_lists.cpp
D	source/blender/functions/types/numeric_lists.hpp
M	source/blender/functions/types/tuple_access-c.cpp
M	source/blender/functions/types/tuple_access-c.h
M	source/blender/functions/types/types-c.cpp
M	source/blender/functions/types/types-c.h
M	source/blender/modifiers/intern/MOD_functionpoints.c
M	source/blender/simulations/bparticles/emitters.cpp
M	source/blender/simulations/bparticles/inserters.cpp
R096	tests/gtests/blenlib/BLI_shared_test.cc	tests/gtests/blenlib/BLI_refcount_test.cc
M	tests/gtests/blenlib/CMakeLists.txt

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

diff --git a/source/blender/blenlib/BLI_shared.hpp b/source/blender/blenlib/BLI_refcount.hpp
similarity index 80%
rename from source/blender/blenlib/BLI_shared.hpp
rename to source/blender/blenlib/BLI_refcount.hpp
index 9ab747c4770..30305ea08cc 100644
--- a/source/blender/blenlib/BLI_shared.hpp
+++ b/source/blender/blenlib/BLI_refcount.hpp
@@ -1,19 +1,14 @@
 #pragma once
 
-/* Objects with shared ownership require a reference
- * counter, so that it can be freed when it is not
- * referenced anymore.
+/* Objects with shared ownership require a reference counter, so that they can be freed when they
+ * are not referenced anymore.
  *
- * Classes can subclass RefCountedBase to be extended
- * with an intrusive reference count (the counter is
- * stored directly in the object). This is necessary,
- * because the object might have to be used by different
- * languages (C, C++, Python).
+ * Classes can subclass RefCounter to be extended with an intrusive reference count (the counter is
+ * stored directly in the object). This is necessary, because the object might have to be used by
+ * different languages (C, C++, Python).
  *
- * To avoid error-prone manual reference counting,
- * there is an AutoRefCount class that works similar
- * to std::shared, but deals with objects of type
- * RefCountedBase.
+ * To avoid error-prone manual reference counting, there is an AutoRefCount class that works
+ * similar to std::shared, but deals with objects of type RefCounter.
  */
 
 #include <atomic>
@@ -22,14 +17,14 @@
 
 namespace BLI {
 
-class RefCountedBase {
+class RefCounter {
  private:
   std::atomic<int> m_refcount;
 
  protected:
-  virtual ~RefCountedBase(){};
+  virtual ~RefCounter(){};
 
-  RefCountedBase() : m_refcount(1)
+  RefCounter() : m_refcount(1)
   {
   }
 
diff --git a/source/blender/blenlib/BLI_shared_immutable.hpp b/source/blender/blenlib/BLI_shared_immutable.hpp
deleted file mode 100644
index 2d1e787d4a9..00000000000
--- a/source/blender/blenlib/BLI_shared_immutable.hpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#pragma once
-
-/* A shared immutable type has a reference count and
- * is freed automatically, when it is not used anymore.
- * Furthermore, it must not be modified, when it is
- * referenced in two or more places.
- *
- * When the reference is one, it can be mutated.
- *
- * This approach reduces the amount of defensive
- * copies of data (data that is copied to make sure
- * that nobody does not change it anymore). Instead,
- * to one just have to increase the user count.
- *
- * A copy has to be made, when the user count is >= 2.
- *
- * Reference counting can be automated with the
- * AutoRefCount class.
- */
-
-#include "BLI_shared.hpp"
-
-namespace BLI {
-
-class SharedImmutable : protected RefCountedBase {
- private:
-  SharedImmutable(SharedImmutable &other) = delete;
-
-  template<typename> friend class AutoRefCount;
-
- public:
-  SharedImmutable() : RefCountedBase()
-  {
-  }
-
-  virtual ~SharedImmutable()
-  {
-  }
-
-  void new_user()
-  {
-    this->incref();
-  }
-
-  void remove_user()
-  {
-    this->decref();
-  }
-
-  int users() const
-  {
-    return this->refcount();
-  }
-
-  bool is_mutable() const
-  {
-    return this->users() == 1;
-  }
-
-  bool is_immutable() const
-  {
-    return this->users() > 1;
-  }
-
-  void assert_mutable() const
-  {
-    BLI_assert(this->is_mutable());
-  }
-};
-
-} /* namespace BLI */
diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt
index 47b3d480d71..f76678528db 100644
--- a/source/blender/blenlib/CMakeLists.txt
+++ b/source/blender/blenlib/CMakeLists.txt
@@ -249,7 +249,7 @@ set(SRC
   BLI_optional.hpp
   BLI_range.hpp
   intern/BLI_range.cpp
-  BLI_shared.hpp
+  BLI_refcount.hpp
   BLI_vector.hpp
   BLI_map.hpp
   BLI_multi_map.hpp
diff --git a/source/blender/functions/CMakeLists.txt b/source/blender/functions/CMakeLists.txt
index 99c73c4621a..f2898142223 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -58,6 +58,8 @@ set(SRC
   backends/tuple/cpp_type_info.cpp
   backends/tuple/tuple.hpp
   backends/tuple/tuple.cpp
+  backends/tuple/list.hpp
+  backends/tuple/list.cpp
   backends/tuple/tuple-c.h
   backends/tuple/tuple-c.cpp
 
@@ -99,8 +101,7 @@ set(SRC
   backends/llvm/context_pool.cpp
 
   types/lists.hpp
-  types/numeric_lists.hpp
-  types/numeric_lists.cpp
+  types/lists.cpp
   types/numeric.hpp
   types/numeric.cpp
   types/boolean.hpp
diff --git a/source/blender/functions/FN_tuple.hpp b/source/blender/functions/FN_tuple.hpp
index f070347c1b0..63426b10985 100644
--- a/source/blender/functions/FN_tuple.hpp
+++ b/source/blender/functions/FN_tuple.hpp
@@ -3,3 +3,4 @@
 #include "FN_tuple-c.h"
 #include "backends/tuple/cpp_type_info.hpp"
 #include "backends/tuple/tuple.hpp"
+#include "backends/tuple/list.hpp"
diff --git a/source/blender/functions/FN_types.hpp b/source/blender/functions/FN_types.hpp
index 69afb88d56f..39c99ef598d 100644
--- a/source/blender/functions/FN_types.hpp
+++ b/source/blender/functions/FN_types.hpp
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "FN_types-c.h"
+#include "types/lists.hpp"
 #include "types/numeric.hpp"
-#include "types/numeric_lists.hpp"
 #include "types/boolean.hpp"
 #include "types/external.hpp"
diff --git a/source/blender/functions/backends/tuple/cpp_type_info.hpp b/source/blender/functions/backends/tuple/cpp_type_info.hpp
index b5c2decfefc..b8a5d652d03 100644
--- a/source/blender/functions/backends/tuple/cpp_type_info.hpp
+++ b/source/blender/functions/backends/tuple/cpp_type_info.hpp
@@ -97,7 +97,7 @@ class CPPTypeInfo : public TypeExtension {
   virtual void relocate_to_uninitialized_n(void *src, void *dst, uint n) const = 0;
 };
 
-template<typename T> class CPPTypeInfoForType final : public CPPTypeInfo {
+template<typename T> class CPPTypeInfoForType : public CPPTypeInfo {
  public:
   CPPTypeInfoForType()
       : CPPTypeInfo(
diff --git a/source/blender/functions/backends/tuple/list.cpp b/source/blender/functions/backends/tuple/list.cpp
new file mode 100644
index 00000000000..25f1ceb5241
--- /dev/null
+++ b/source/blender/functions/backends/tuple/list.cpp
@@ -0,0 +1,22 @@
+#include "list.hpp"
+
+namespace FN {
+
+void List::grow(uint min_capacity)
+{
+  if (m_capacity >= min_capacity) {
+    return;
+  }
+
+  uint new_capacity = power_of_2_max_u(min_capacity);
+  void *new_storage = MEM_malloc_arrayN(new_capacity, m_type_info->size(), __func__);
+  m_type_info->relocate_to_uninitialized_n(m_storage, new_storage, m_size);
+
+  if (m_storage != nullptr) {
+    MEM_freeN(m_storage);
+  }
+  m_storage = new_storage;
+  m_capacity = new_capacity;
+}
+
+}  // namespace FN
diff --git a/source/blender/functions/backends/tuple/list.hpp b/source/blender/functions/backends/tuple/list.hpp
new file mode 100644
index 00000000000..240b66dac4a
--- /dev/null
+++ b/source/blender/functions/backends/tuple/list.hpp
@@ -0,0 +1,155 @@
+#pragma once
+
+#include "tuple.hpp"
+#include "BLI_refcount.hpp"
+
+namespace FN {
+
+class List;
+using SharedList = AutoRefCount<List>;
+
+class List : public RefCounter {
+ private:
+  SharedType m_type;
+  CPPTypeInfo *m_type_info;
+  void *m_storage;
+  uint m_size;
+  uint m_capacity;
+
+ public:
+  List() = delete;
+  List(SharedType type) : m_type(std::move(type))
+  {
+    m_type_info = &m_type->extension<CPPTypeInfo>();
+    m_storage = nullptr;
+    m_size = 0;
+    m_capacity = 0;
+  }
+
+  List(List &other) = delete;
+  List(List &&other) = delete;
+  List &operator=(List &other) = delete;
+  List &operator=(List &&other) = delete;
+
+  ~List()
+  {
+    if (m_storage != nullptr) {
+      m_type_info->destruct_n(m_storage, m_size);
+      MEM_freeN(m_storage);
+    }
+  }
+
+  bool is_mutable()
+  {
+    return this->refcount() == 1;
+  }
+
+  SharedList get_mutable()
+  {
+    if (this->is_mutable()) {
+      return SharedList(this);
+    }
+    else {
+      return this->real_copy();
+    }
+  }
+
+  SharedList real_copy()
+  {
+    List *list = new List(m_type);
+    SharedList this_list(this);
+    list->extend__dynamic_copy(this_list);
+    this_list.extract_ptr();
+    return SharedList(list);
+  }
+
+  void append__dynamic_relocate_from_tuple(Tuple &tuple, uint index)
+  {
+    BLI_assert(this->is_mutable());
+    BLI_assert(&tuple.meta().type_info(index) == m_type_info);
+    this->ensure_space_for_one();
+    void *dst = POINTER_OFFSET(m_storage, m_size * m_type_info->size());
+    tuple.relocate_out__dynamic(index, dst);
+    m_size++;
+  }
+
+  void get__dynamic_copy_to_tuple(uint element_index, Tuple &tuple, uint tuple_index)
+  {
+    BLI_assert(this->is_mutable());
+    BLI_assert(&tuple.meta().type_info(tuple_index) == m_type_info);
+    BLI_assert(element_index < m_size);
+    void *src = POINTER_OFFSET(m_storage, element_index * m_type_info->size());
+    tuple.copy_in__dynamic(tuple_index, src);
+  }
+
+  void extend__dynamic_copy(const SharedList &other)
+  {
+    BLI_assert(this->is_mutable());
+    BLI_assert(m_type == other->m_type);
+    List &other_ = other.ref();
+    this->reserve(m_size + other_.size());
+    void *src = other_.m_storage;
+    void *dst = POINTER_OFFSET(m_storage, m_size * m_type_info->size());
+    m_type_info->copy_to_uninitialized_n(src, dst, other_.size());
+    m_size += other_.size();
+  }
+
+  void *storage() const
+  {
+    return m_storage;
+  }
+
+  template<typename T> T *storage() const
+  {
+    BLI_assert(this->can_be_type<T>());
+    return static_cast<T *>(m_storage);
+  }
+
+  template<typename T> ArrayRef<T> as_array_ref() const
+  {
+    BLI_assert(this->can_be_type<T>());
+    return ArrayRef<T>(this->storage<T>(), m_size);
+  }
+
+  template<typename T> bool can_be_type() const
+  {
+    return sizeof(T) == m_type_info->size();
+  }
+
+  uint size() const
+  {
+    return m_size;
+  }
+
+  SharedType &type()
+  {
+    return m_type;
+  }
+
+  void reserve_and_set_size(uint size)
+  {
+    this->reserve(size);
+    m_size = size;
+  }
+
+  void reserve(uint size)
+  {
+    BLI_assert(this->is_mutable());
+    if (size > m_capacity) {
+      this->grow(size);
+    }
+  }
+
+ private:
+  void ensure_space_for_one()
+  {
+    if (m_size < m_capacity) {
+   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list