[Bf-blender-cvs] [5d4bf32c40e] functions: allocate type extensions in type directly

Jacques Lucke noreply at git.blender.org
Thu May 2 11:44:57 CEST 2019


Commit: 5d4bf32c40ee3494c2a675e4519b42e16481abf4
Author: Jacques Lucke
Date:   Thu May 2 11:19:05 2019 +0200
Branches: functions
https://developer.blender.org/rB5d4bf32c40ee3494c2a675e4519b42e16481abf4

allocate type extensions in type directly

This makes sense, since every extension is owned
by a Type object. Also this improves thread safety.

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

M	source/blender/blenlib/BLI_composition.hpp
M	source/blender/functions/core/type.hpp
M	source/blender/functions/types/boolean.cpp
M	source/blender/functions/types/numeric.cpp
M	source/blender/functions/types/numeric_lists.cpp

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

diff --git a/source/blender/blenlib/BLI_composition.hpp b/source/blender/blenlib/BLI_composition.hpp
index ad0e6b6c839..68e67b764f9 100644
--- a/source/blender/blenlib/BLI_composition.hpp
+++ b/source/blender/blenlib/BLI_composition.hpp
@@ -35,6 +35,11 @@ class Composition {
     }
   }
 
+  template<typename T> inline bool has() const
+  {
+    return m_elements.contains(this->get_key<T>());
+  }
+
   ~Composition()
   {
     for (const Entry &entry : m_elements.values()) {
diff --git a/source/blender/functions/core/type.hpp b/source/blender/functions/core/type.hpp
index 11ee8feba13..0b774e324e4 100644
--- a/source/blender/functions/core/type.hpp
+++ b/source/blender/functions/core/type.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <string>
+#include <mutex>
 #include "BLI_composition.hpp"
 #include "BLI_shared.hpp"
 
@@ -8,7 +9,23 @@ namespace FN {
 
 using namespace BLI;
 
+class Type;
+
 class TypeExtension {
+ private:
+  Type *m_owner = nullptr;
+  friend Type;
+
+  void set_owner(Type *owner)
+  {
+    m_owner = owner;
+  }
+
+ public:
+  Type *owner() const
+  {
+    return m_owner;
+  }
 };
 
 class Type final : public RefCountedBase {
@@ -23,16 +40,35 @@ class Type final : public RefCountedBase {
     return m_name;
   }
 
-  template<typename T> inline T *extension() const
+  template<typename T> bool has_extension() const
+  {
+    std::lock_guard<std::mutex> lock(m_extension_mutex);
+    return m_extensions.has<T>();
+  }
+
+  template<typename T> T *extension() const
   {
+    /* TODO: Check if we really need a lock here.
+     *   Since extensions can't be removed, it might be
+     *   to access existing extensions without a lock. */
+    std::lock_guard<std::mutex> lock(m_extension_mutex);
     return m_extensions.get<T>();
   }
 
-  template<typename T> void extend(T *extension)
+  template<typename T, typename... Args> bool extend(Args &&... args)
   {
-    BLI_assert(m_extensions.get<T>() == nullptr);
+    std::lock_guard<std::mutex> lock(m_extension_mutex);
     static_assert(std::is_base_of<TypeExtension, T>::value, "");
-    m_extensions.add(extension);
+
+    if (m_extensions.has<T>()) {
+      return false;
+    }
+    else {
+      T *new_extension = new T(std::forward<Args>(args)...);
+      new_extension->set_owner(this);
+      m_extensions.add(new_extension);
+      return true;
+    }
   }
 
   friend bool operator==(const Type &a, const Type &b)
@@ -43,6 +79,7 @@ class Type final : public RefCountedBase {
  private:
   std::string m_name;
   Composition m_extensions;
+  mutable std::mutex m_extension_mutex;
 };
 
 using SharedType = AutoRefCount<Type>;
diff --git a/source/blender/functions/types/boolean.cpp b/source/blender/functions/types/boolean.cpp
index 377b4c1a34b..33c7db570e4 100644
--- a/source/blender/functions/types/boolean.cpp
+++ b/source/blender/functions/types/boolean.cpp
@@ -34,8 +34,8 @@ class LLVMBool : public TrivialLLVMTypeInfo {
 LAZY_INIT_REF__NO_ARG(SharedType, GET_TYPE_bool)
 {
   SharedType type = SharedType::New("Bool");
-  type->extend(new CPPTypeInfoForType<bool>());
-  type->extend(new LLVMBool());
+  type->extend<CPPTypeInfoForType<bool>>();
+  type->extend<LLVMBool>();
   return type;
 }
 
diff --git a/source/blender/functions/types/numeric.cpp b/source/blender/functions/types/numeric.cpp
index 4e59a8003c7..a214b1bf5a5 100644
--- a/source/blender/functions/types/numeric.cpp
+++ b/source/blender/functions/types/numeric.cpp
@@ -10,18 +10,18 @@ namespace Types {
 LAZY_INIT_REF__NO_ARG(SharedType, GET_TYPE_float)
 {
   SharedType type = SharedType::New("Float");
-  type->extend(new CPPTypeInfoForType<float>());
-  type->extend(new PackedLLVMTypeInfo(
-      [](llvm::LLVMContext &context) { return llvm::Type::getFloatTy(context); }));
+  type->extend<CPPTypeInfoForType<float>>();
+  type->extend<PackedLLVMTypeInfo>(
+      [](llvm::LLVMContext &context) { return llvm::Type::getFloatTy(context); });
   return type;
 }
 
 LAZY_INIT_REF__NO_ARG(SharedType, GET_TYPE_int32)
 {
   SharedType type = SharedType::New("Int32");
-  type->extend(new CPPTypeInfoForType<int32_t>());
-  type->extend(new PackedLLVMTypeInfo(
-      [](llvm::LLVMContext &context) { return llvm::Type::getIntNTy(context, 32); }));
+  type->extend<CPPTypeInfoForType<int32_t>>();
+  type->extend<PackedLLVMTypeInfo>(
+      [](llvm::LLVMContext &context) { return llvm::Type::getIntNTy(context, 32); });
   return type;
 }
 
@@ -67,8 +67,8 @@ class FloatVectorType : public TrivialLLVMTypeInfo {
 LAZY_INIT_REF__NO_ARG(SharedType, GET_TYPE_fvec3)
 {
   SharedType type = SharedType::New("FVec3");
-  type->extend(new CPPTypeInfoForType<Vector>());
-  type->extend(new FloatVectorType(3));
+  type->extend<CPPTypeInfoForType<Vector>>();
+  type->extend<FloatVectorType>(3);
   return type;
 }
 
diff --git a/source/blender/functions/types/numeric_lists.cpp b/source/blender/functions/types/numeric_lists.cpp
index 3b50d554246..5274ae223f3 100644
--- a/source/blender/functions/types/numeric_lists.cpp
+++ b/source/blender/functions/types/numeric_lists.cpp
@@ -7,40 +7,32 @@
 namespace FN {
 namespace Types {
 
-template<typename T> class ListLLVMTypeInfo : public LLVMTypeInfo {
- private:
-  static void *copy_func(void *value)
-  {
-    List<T> *list = (List<T> *)value;
-    list->new_user();
-    return list;
-  }
-
-  static void free_func(void *value)
-  {
-    List<T> *list = (List<T> *)value;
-    list->remove_user();
-  }
+template<typename T> static void *copy_func(void *value)
+{
+  List<T> *list = (List<T> *)value;
+  list->new_user();
+  return list;
+}
 
-  static void *default_func()
-  {
-    return new List<T>();
-  }
+template<typename T> static void free_func(void *value)
+{
+  List<T> *list = (List<T> *)value;
+  list->remove_user();
+}
 
- public:
-  static LLVMTypeInfo *Create()
-  {
-    static_assert(sizeof(SharedList<T>) == sizeof(List<T> *),
-                  "Currently it is assumed that only a pointer to the list is stored");
-    return new PointerLLVMTypeInfo(copy_func, free_func, default_func);
-  }
-};
+template<typename T> static void *default_func()
+{
+  return new List<T>();
+}
 
 template<typename T> SharedType create_list_type(std::string name)
 {
+  static_assert(sizeof(SharedList<T>) == sizeof(List<T> *),
+                "Currently it is assumed that only a pointer to the list is stored");
+
   SharedType type = SharedType::New(name);
-  type->extend(new CPPTypeInfoForType<SharedList<T>>());
-  type->extend(ListLLVMTypeInfo<T>::Create());
+  type->extend<CPPTypeInfoForType<SharedList<T>>>();
+  type->extend<PointerLLVMTypeInfo>(copy_func<T>, free_func<T>, default_func<T>);
   return type;
 }



More information about the Bf-blender-cvs mailing list