1
0
Эх сурвалжийг харах

any: doc + test for configurable sbo

Michele Caini 5 жил өмнө
parent
commit
1aec7f71b8

+ 20 - 0
docs/md/core.md

@@ -14,6 +14,7 @@
   * [Conflicts](#conflicts)
   * [Conflicts](#conflicts)
 * [Monostate](#monostate)
 * [Monostate](#monostate)
 * [Any as in any type](#any-as-in-any-type)
 * [Any as in any type](#any-as-in-any-type)
+  * [Small buffer optimization](#small-buffer-optimization)
 * [Type support](#type-support)
 * [Type support](#type-support)
   * [Type info](#type-info)
   * [Type info](#type-info)
     * [Almost unique identifiers](#almost-unique-identifiers)
     * [Almost unique identifiers](#almost-unique-identifiers)
@@ -312,6 +313,25 @@ The only difference is that, in the case of `EnTT`, these won't raise exceptions
 but will only trigger an assert in debug mode, otherwise resulting in undefined
 but will only trigger an assert in debug mode, otherwise resulting in undefined
 behavior in case of misuse in release mode.
 behavior in case of misuse in release mode.
 
 
+## Small buffer optimization
+
+The `any` class uses a technique called _small buffer optimization_ to reduce
+the number of allocations where possible.<br/>
+The default reserved size for an instance of `any` is `sizeof(double[2])`.
+However, this is also configurable if needed. In fact, `any` is defined as an
+alias for `basic_any<Len>`, where `Len` is just the size above.<br/>
+Users can easily use a custom size or define their own alias:
+
+```cpp
+using my_any = entt::basic_any<sizeof(double[4])>;
+```
+
+This feature, in addition to allowing the choice of a size that best suits the
+needs of an application, also reserves the possibility of forcing dynamic
+creation of objects during construction.<br/>
+In fact, if the size is 0, `any` will avoid the use of any optimization, in fact
+always dynamically allocating objects (except for aliasing cases).
+
 # Type support
 # Type support
 
 
 `EnTT` provides some basic information about types of all kinds.<br/>
 `EnTT` provides some basic information about types of all kinds.<br/>

+ 2 - 2
src/entt/entity/registry.hpp

@@ -1520,7 +1520,7 @@ public:
     template<typename Type, typename... Args>
     template<typename Type, typename... Args>
     Type & set(Args &&... args) {
     Type & set(Args &&... args) {
         unset<Type>();
         unset<Type>();
-        vars.push_back(any{std::in_place_type<Type>, std::forward<Args>(args)...});
+        vars.emplace_back(std::in_place_type<Type>, std::forward<Args>(args)...);
         return any_cast<Type &>(vars.back());
         return any_cast<Type &>(vars.back());
     }
     }
 
 
@@ -1621,7 +1621,7 @@ public:
     }
     }
 
 
 private:
 private:
-    std::vector<any> vars{};
+    std::vector<basic_any<0u>> vars{};
     std::vector<pool_data> pools{};
     std::vector<pool_data> pools{};
     std::vector<group_data> groups{};
     std::vector<group_data> groups{};
     std::vector<entity_type> entities{};
     std::vector<entity_type> entities{};

+ 14 - 0
test/entt/core/any.cpp

@@ -870,3 +870,17 @@ TEST(Any, CopyMoveReference) {
     test(std::ref(value));
     test(std::ref(value));
     test(std::cref(value));
     test(std::cref(value));
 }
 }
+
+TEST(Any, SBOVsForcedDynamic) {
+    entt::any sbo{42};
+    const auto sbo_ptr = sbo.data();
+    entt::any sbo_copy = std::move(sbo);
+
+    ASSERT_NE(sbo_ptr, sbo_copy.data());
+
+    entt::basic_any<0u> dyn{42};
+    const auto dyn_ptr = dyn.data();
+    entt::any dyn_copy = std::move(dyn);
+
+    ASSERT_NE(dyn_ptr, dyn_copy.data());
+}