Explorar o código

registry/dispatcher/emitter: removed ::discard, updated test and doc

Michele Caini %!s(int64=6) %!d(string=hai) anos
pai
achega
43766406ae

+ 17 - 22
docs/md/lib.md

@@ -32,10 +32,12 @@ erased on the other side of a boundary.<br/>
 The `type_info` class template is how identifiers are generated and thus made
 The `type_info` class template is how identifiers are generated and thus made
 available to the rest of the library.
 available to the rest of the library.
 
 
-The only case in which this may arouse some interest is in case of conflicts
-between identifiers (definitely uncommon though) or where the default solution
-proposed by `EnTT` is not suitable for the user's purposes.<br/>
-Please refer to the dedicated section for more details.
+In general, this class doesn't arouse much interest. The only exception is in
+case of conflicts between identifiers (definitely uncommon though) or where the
+default solution proposed by `EnTT` isn't suitable for the user's purposes.<br/>
+The section dedicated to this core class contains all the details to get around
+the problem in a concise and elegant way. Please refer to the specific
+documentation.
 
 
 # Meta context
 # Meta context
 
 
@@ -80,29 +82,22 @@ available.
 
 
 There is another subtle problem due to memory management that can lead to
 There is another subtle problem due to memory management that can lead to
 headaches.<br/>
 headaches.<br/>
-This can occur where there are pools of objects (such as components or events)
-dynamically created on demand.
+It can occur where there are pools of objects (such as components or events)
+dynamically created on demand. This is usually not a problem when working with
+linked libraries that rely on the same dynamic runtime. However, it can occur in
+the case of plugins or statically linked runtimes.
 
 
 As an example, imagine creating an instance of `registry` in the main executable
 As an example, imagine creating an instance of `registry` in the main executable
-and share it with a plugin. If the latter starts working with a component that
+and sharing it with a plugin. If the latter starts working with a component that
 is unknown to the former, a dedicated pool is created within the registry on
 is unknown to the former, a dedicated pool is created within the registry on
 first use.<br/>
 first use.<br/>
 As one can guess, this pool is instantiated on a different side of the boundary
 As one can guess, this pool is instantiated on a different side of the boundary
 from the `registry`. Therefore, the instance is now managing memory from
 from the `registry`. Therefore, the instance is now managing memory from
 different spaces and this can quickly lead to crashes if not properly addressed.
 different spaces and this can quickly lead to crashes if not properly addressed.
 
 
-Fortunately, all classes that could potentially suffer from this problem offer
-also a `discard` member function to get rid of these pools:
-
-```cpp
-registry.discard<local_type>();
-```
-
-This is all there is to do to get around this. Again, `discard` is only to be
-invoked if it's certain that the container and pools are instantiated on
-different sides of the boundary.
-
-If in doubts or to avoid risks, simply invoke the `prepare` member function or
-any of the other functions that refer to the desired type to force the
-generation of the pools that are used on both sides of the boundary.<br/>
-This is something to be done usually in the main context when needed.
+To overcome the risk, it's recommended to use well-defined interfaces that make
+fundamental types pass through the boundaries, isolating the instances of the
+`EnTT` classes from time to time and as appropriate.<br/>
+Refer to the test suite for some examples, read the documentation available
+online about this type of issues or consult someone who has already had such
+experiences to avoid problems.

+ 1 - 12
src/entt/entity/registry.hpp

@@ -155,7 +155,7 @@ class basic_registry {
         template<typename Component>
         template<typename Component>
         void maybe_valid_if(const Entity entt, basic_registry &owner) {
         void maybe_valid_if(const Entity entt, basic_registry &owner) {
             static_assert(std::is_same_v<Component, std::decay_t<Component>>);
             static_assert(std::is_same_v<Component, std::decay_t<Component>>);
-            const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
+            [[maybe_unused]] const auto cpools = std::forward_as_tuple(owner.assure<Owned>()...);
 
 
             const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<pool_type<Owned> &>(cpools).has(entt)) && ...)
             const auto is_valid = ((std::is_same_v<Component, Owned> || std::get<pool_type<Owned> &>(cpools).has(entt)) && ...)
                     && ((std::is_same_v<Component, Get> || owner.assure<Get>().has(entt)) && ...)
                     && ((std::is_same_v<Component, Get> || owner.assure<Get>().has(entt)) && ...)
@@ -302,17 +302,6 @@ public:
         assure<Component>(std::forward<Args>(args)...);
         assure<Component>(std::forward<Args>(args)...);
     }
     }
 
 
-    /**
-     * @brief Discards the pools for the given components.
-     * @tparam Component Types of components for which to discard the pools.
-     */
-    template<typename... Component>
-    void discard() {
-        pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&pdata) {
-            return ((pdata.type_id == type_info<Component>::id()) || ...);
-        }), pools.end());
-    }
-
     /**
     /**
      * @brief Returns the number of existing components of the given type.
      * @brief Returns the number of existing components of the given type.
      * @tparam Component Type of component of which to return the size.
      * @tparam Component Type of component of which to return the size.

+ 0 - 11
src/entt/signal/dispatcher.hpp

@@ -98,17 +98,6 @@ class dispatcher {
     }
     }
 
 
 public:
 public:
-    /**
-     * @brief Discards the pools for the given events.
-     * @tparam Event Types of events for which to discard the pools.
-     */
-    template<typename... Event>
-    void discard() {
-        pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&cpool) {
-            return ((cpool->type_id() == type_info<Event>::id()) || ...);
-        }), pools.end());
-    }
-
     /**
     /**
      * @brief Returns a sink object for the given event.
      * @brief Returns a sink object for the given event.
      *
      *

+ 0 - 11
src/entt/signal/emitter.hpp

@@ -186,17 +186,6 @@ public:
     /*! @brief Default move assignment operator. @return This emitter. */
     /*! @brief Default move assignment operator. @return This emitter. */
     emitter & operator=(emitter &&) = default;
     emitter & operator=(emitter &&) = default;
 
 
-    /**
-     * @brief Discards the pools for the given events.
-     * @tparam Event Types of events for which to discard the pools.
-     */
-    template<typename... Event>
-    void discard() {
-        pools.erase(std::remove_if(pools.begin(), pools.end(), [](auto &&cpool) {
-            return ((cpool->type_id() == type_info<Event>::id()) || ...);
-        }), pools.end());
-    }
-
     /**
     /**
      * @brief Emits the given event.
      * @brief Emits the given event.
      *
      *

+ 16 - 3
test/lib/dispatcher_plugin/main.cpp

@@ -2,10 +2,22 @@
 
 
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
-#include <entt/core/utility.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/dispatcher.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(entt::dispatcher &ref)
+    : dispatcher{&ref}
+{}
+
+void proxy::trigger(message msg) {
+    dispatcher->trigger(msg);
+}
+
+void proxy::trigger(event ev) {
+    dispatcher->trigger(ev);
+}
+
 struct listener {
 struct listener {
     void on(message msg) { value = msg.payload; }
     void on(message msg) { value = msg.payload; }
     int value{};
     int value{};
@@ -13,14 +25,15 @@ struct listener {
 
 
 TEST(Lib, Dispatcher) {
 TEST(Lib, Dispatcher) {
     entt::dispatcher dispatcher;
     entt::dispatcher dispatcher;
+    proxy handler{dispatcher};
     listener listener;
     listener listener;
 
 
     ASSERT_EQ(listener.value, 0);
     ASSERT_EQ(listener.value, 0);
 
 
-    dispatcher.sink<message>().connect<entt::overload<void(message)>(&listener::on)>(listener);
+    dispatcher.sink<message>().connect<&listener::on>(listener);
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &dispatcher;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 2 - 5
test/lib/dispatcher_plugin/plugin.cpp

@@ -1,16 +1,13 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/signal/dispatcher.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
-        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
-        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
+        static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(event{});
+        static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(message{42});
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<entt::dispatcher *>(ctx->userdata)->discard<event>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 16 - 0
test/lib/dispatcher_plugin/proxy.h

@@ -0,0 +1,16 @@
+#ifndef ENTT_LIB_DISPATCHER_PLUGIN_PROXY_H
+#define ENTT_LIB_DISPATCHER_PLUGIN_PROXY_H
+
+#include <entt/signal/fwd.hpp>
+#include "types.h"
+
+struct proxy: dispatcher_proxy {
+    proxy(entt::dispatcher &);
+    void trigger(message) override;
+    void trigger(event) override;
+
+private:
+    entt::dispatcher *dispatcher;
+};
+
+#endif

+ 6 - 0
test/lib/dispatcher_plugin/types.h

@@ -7,4 +7,10 @@ struct message {
 
 
 struct event {};
 struct event {};
 
 
+struct dispatcher_proxy {
+    virtual ~dispatcher_proxy() = default;
+    virtual void trigger(message) = 0;
+    virtual void trigger(event) = 0;
+};
+
 #endif
 #endif

+ 16 - 3
test/lib/dispatcher_plugin_std/main.cpp

@@ -2,10 +2,22 @@
 
 
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
-#include <entt/core/utility.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/dispatcher.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(entt::dispatcher &ref)
+    : dispatcher{&ref}
+{}
+
+void proxy::trigger(message msg) {
+    dispatcher->trigger(msg);
+}
+
+void proxy::trigger(event ev) {
+    dispatcher->trigger(ev);
+}
+
 struct listener {
 struct listener {
     void on(message msg) { value = msg.payload; }
     void on(message msg) { value = msg.payload; }
     int value{};
     int value{};
@@ -13,14 +25,15 @@ struct listener {
 
 
 TEST(Lib, Dispatcher) {
 TEST(Lib, Dispatcher) {
     entt::dispatcher dispatcher;
     entt::dispatcher dispatcher;
+    proxy handler{dispatcher};
     listener listener;
     listener listener;
 
 
     ASSERT_EQ(listener.value, 0);
     ASSERT_EQ(listener.value, 0);
 
 
-    dispatcher.sink<message>().connect<entt::overload<void(message)>(&listener::on)>(listener);
+    dispatcher.sink<message>().connect<&listener::on>(listener);
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &dispatcher;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 2 - 5
test/lib/dispatcher_plugin_std/plugin.cpp

@@ -1,16 +1,13 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/signal/dispatcher.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
-        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
-        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
+        static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(event{});
+        static_cast<dispatcher_proxy *>(ctx->userdata)->trigger(message{42});
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<entt::dispatcher *>(ctx->userdata)->discard<event>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 16 - 0
test/lib/dispatcher_plugin_std/proxy.h

@@ -0,0 +1,16 @@
+#ifndef ENTT_LIB_DISPATCHER_PLUGIN_STD_PROXY_H
+#define ENTT_LIB_DISPATCHER_PLUGIN_STD_PROXY_H
+
+#include <entt/signal/fwd.hpp>
+#include "types.h"
+
+struct proxy: dispatcher_proxy {
+    proxy(entt::dispatcher &);
+    void trigger(message) override;
+    void trigger(event) override;
+
+private:
+    entt::dispatcher *dispatcher;
+};
+
+#endif

+ 5 - 22
test/lib/dispatcher_plugin_std/types.h

@@ -1,33 +1,16 @@
 #ifndef ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
 #ifndef ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_DISPATCHER_PLUGIN_STD_TYPES_H
 
 
-#include <type_traits>
-#include <entt/core/hashed_string.hpp>
-#include <entt/core/type_info.hpp>
-
-template<typename>
-struct event_id;
-
-#define ASSIGN_TYPE_ID(clazz)\
-    template<>\
-    struct event_id<clazz>\
-        : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
-    {}
-
-template<typename Type>
-struct entt::type_info<Type> {
-    static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
-        return event_id<Type>::value;
-    }
-};
-
 struct message {
 struct message {
     int payload;
     int payload;
 };
 };
 
 
 struct event {};
 struct event {};
 
 
-ASSIGN_TYPE_ID(message);
-ASSIGN_TYPE_ID(event);
+struct dispatcher_proxy {
+    virtual ~dispatcher_proxy() = default;
+    virtual void trigger(message) = 0;
+    virtual void trigger(event) = 0;
+};
 
 
 #endif
 #endif

+ 15 - 1
test/lib/emitter_plugin/main.cpp

@@ -3,10 +3,24 @@
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/signal/emitter.hpp>
 #include <entt/signal/emitter.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(test_emitter &ref)
+    : emitter{&ref}
+{}
+
+void proxy::publish(message msg) {
+    emitter->publish<message>(msg);
+}
+
+void proxy::publish(event ev) {
+    emitter->publish<event>(ev);
+}
+
 TEST(Lib, Emitter) {
 TEST(Lib, Emitter) {
     test_emitter emitter;
     test_emitter emitter;
+    proxy handler{emitter};
     int value{};
     int value{};
 
 
     ASSERT_EQ(value, 0);
     ASSERT_EQ(value, 0);
@@ -14,7 +28,7 @@ TEST(Lib, Emitter) {
     emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
     emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &emitter;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 3 - 6
test/lib/emitter_plugin/plugin.cpp

@@ -1,17 +1,14 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/signal/emitter.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
-        static_cast<test_emitter *>(ctx->userdata)->publish<event>();
-        static_cast<test_emitter *>(ctx->userdata)->publish<message>(42);
-        static_cast<test_emitter *>(ctx->userdata)->publish<message>(3);
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(event{});
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(message{42});
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(message{3});
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<test_emitter *>(ctx->userdata)->discard<event>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 15 - 0
test/lib/emitter_plugin/proxy.h

@@ -0,0 +1,15 @@
+#ifndef ENTT_LIB_EMITTER_PLUGIN_PROXY_H
+#define ENTT_LIB_EMITTER_PLUGIN_PROXY_H
+
+#include "types.h"
+
+struct proxy: emitter_proxy {
+    proxy(test_emitter &);
+    void publish(message) override;
+    void publish(event) override;
+
+private:
+    test_emitter *emitter;
+};
+
+#endif

+ 6 - 0
test/lib/emitter_plugin/types.h

@@ -13,4 +13,10 @@ struct message {
 
 
 struct event {};
 struct event {};
 
 
+struct emitter_proxy {
+    virtual ~emitter_proxy() = default;
+    virtual void publish(message) = 0;
+    virtual void publish(event) = 0;
+};
+
 #endif
 #endif

+ 15 - 1
test/lib/emitter_plugin_std/main.cpp

@@ -3,10 +3,24 @@
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/signal/emitter.hpp>
 #include <entt/signal/emitter.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(test_emitter &ref)
+    : emitter{&ref}
+{}
+
+void proxy::publish(message msg) {
+    emitter->publish<message>(msg);
+}
+
+void proxy::publish(event ev) {
+    emitter->publish<event>(ev);
+}
+
 TEST(Lib, Emitter) {
 TEST(Lib, Emitter) {
     test_emitter emitter;
     test_emitter emitter;
+    proxy handler{emitter};
     int value{};
     int value{};
 
 
     ASSERT_EQ(value, 0);
     ASSERT_EQ(value, 0);
@@ -14,7 +28,7 @@ TEST(Lib, Emitter) {
     emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
     emitter.once<message>([&](message msg, test_emitter &) { value = msg.payload; });
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &emitter;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 3 - 6
test/lib/emitter_plugin_std/plugin.cpp

@@ -1,17 +1,14 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/signal/emitter.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
-        static_cast<test_emitter *>(ctx->userdata)->publish<event>();
-        static_cast<test_emitter *>(ctx->userdata)->publish<message>(42);
-        static_cast<test_emitter *>(ctx->userdata)->publish<message>(3);
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(event{});
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(message{42});
+        static_cast<emitter_proxy *>(ctx->userdata)->publish(message{3});
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<test_emitter *>(ctx->userdata)->discard<event>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 15 - 0
test/lib/emitter_plugin_std/proxy.h

@@ -0,0 +1,15 @@
+#ifndef ENTT_LIB_EMITTER_PLUGIN_STD_PROXY_H
+#define ENTT_LIB_EMITTER_PLUGIN_STD_PROXY_H
+
+#include "types.h"
+
+struct proxy: emitter_proxy {
+    proxy(test_emitter &);
+    void publish(message) override;
+    void publish(event) override;
+
+private:
+    test_emitter *emitter;
+};
+
+#endif

+ 5 - 21
test/lib/emitter_plugin_std/types.h

@@ -1,27 +1,8 @@
 #ifndef ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
 #ifndef ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_EMITTER_PLUGIN_STD_TYPES_H
 
 
-#include <type_traits>
-#include <entt/core/hashed_string.hpp>
-#include <entt/core/type_info.hpp>
 #include <entt/signal/emitter.hpp>
 #include <entt/signal/emitter.hpp>
 
 
-template<typename>
-struct event_id;
-
-#define ASSIGN_TYPE_ID(clazz)\
-    template<>\
-    struct event_id<clazz>\
-        : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
-    {}
-
-template<typename Type>
-struct entt::type_info<Type> {
-    static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
-        return event_id<Type>::value;
-    }
-};
-
 struct test_emitter
 struct test_emitter
         : entt::emitter<test_emitter>
         : entt::emitter<test_emitter>
 {};
 {};
@@ -32,7 +13,10 @@ struct message {
 
 
 struct event {};
 struct event {};
 
 
-ASSIGN_TYPE_ID(message);
-ASSIGN_TYPE_ID(event);
+struct emitter_proxy {
+    virtual ~emitter_proxy() = default;
+    virtual void publish(message) = 0;
+    virtual void publish(event) = 0;
+};
 
 
 #endif
 #endif

+ 17 - 1
test/lib/registry_plugin/main.cpp

@@ -3,10 +3,26 @@
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(entt::registry &ref)
+    : registry{&ref}
+{}
+
+void proxy::for_each(void(*cb)(position &, velocity &)) {
+    registry->view<position, velocity>().each(cb);
+}
+
+void proxy::assign(velocity vel) {
+    for(auto entity: registry->view<position>()) {
+        registry->assign<velocity>(entity, vel);
+    }
+}
+
 TEST(Lib, Registry) {
 TEST(Lib, Registry) {
     entt::registry registry;
     entt::registry registry;
+    proxy handler{registry};
 
 
     for(auto i = 0; i < 3; ++i) {
     for(auto i = 0; i < 3; ++i) {
         const auto entity = registry.create();
         const auto entity = registry.create();
@@ -14,7 +30,7 @@ TEST(Lib, Registry) {
     }
     }
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &registry;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 5 - 12
test/lib/registry_plugin/plugin.cpp

@@ -1,28 +1,21 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/entity/registry.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
         [ctx]() {
         [ctx]() {
-            auto *registry = static_cast<entt::registry *>(ctx->userdata);
-            // forces the creation of the pool for the velocity component
-            registry->prepare<velocity>();
+            auto *proxy = static_cast<registry_proxy *>(ctx->userdata);
 
 
-            for(auto entity: registry->view<position>()) {
-                registry->assign<velocity>(entity, 1., 1.);
-            }
+            proxy->assign({1., 1.});
 
 
-            registry->view<position, velocity>().each([](auto &pos, auto &vel) {
-                pos.x += 16 * vel.dx;
-                pos.y += 16 * vel.dy;
+            proxy->for_each([](auto &pos, auto &vel) {
+                pos.x += static_cast<int>(16 * vel.dx);
+                pos.y += static_cast<int>(16 * vel.dy);
             });
             });
         }();
         }();
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<entt::registry *>(ctx->userdata)->discard<velocity>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 16 - 0
test/lib/registry_plugin/proxy.h

@@ -0,0 +1,16 @@
+#ifndef ENTT_LIB_REGISTRY_PLUGIN_PROXY_H
+#define ENTT_LIB_REGISTRY_PLUGIN_PROXY_H
+
+#include <entt/entity/fwd.hpp>
+#include "types.h"
+
+struct proxy: registry_proxy {
+    proxy(entt::registry &);
+    void for_each(void(*)(position &, velocity &)) override;
+    void assign(velocity) override;
+
+private:
+    entt::registry *registry;
+};
+
+#endif

+ 6 - 0
test/lib/registry_plugin/types.h

@@ -11,4 +11,10 @@ struct velocity {
     double dy;
     double dy;
 };
 };
 
 
+struct registry_proxy {
+    virtual ~registry_proxy() = default;
+    virtual void for_each(void(*)(position &, velocity &)) = 0;
+    virtual void assign(velocity) = 0;
+};
+
 #endif
 #endif

+ 17 - 1
test/lib/registry_plugin_std/main.cpp

@@ -3,10 +3,26 @@
 #include <cr.h>
 #include <cr.h>
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <entt/entity/registry.hpp>
 #include <entt/entity/registry.hpp>
+#include "proxy.h"
 #include "types.h"
 #include "types.h"
 
 
+proxy::proxy(entt::registry &ref)
+    : registry{&ref}
+{}
+
+void proxy::for_each(void(*cb)(position &, velocity &)) {
+    registry->view<position, velocity>().each(cb);
+}
+
+void proxy::assign(velocity vel) {
+    for(auto entity: registry->view<position>()) {
+        registry->assign<velocity>(entity, vel);
+    }
+}
+
 TEST(Lib, Registry) {
 TEST(Lib, Registry) {
     entt::registry registry;
     entt::registry registry;
+    proxy handler{registry};
 
 
     for(auto i = 0; i < 3; ++i) {
     for(auto i = 0; i < 3; ++i) {
         const auto entity = registry.create();
         const auto entity = registry.create();
@@ -14,7 +30,7 @@ TEST(Lib, Registry) {
     }
     }
 
 
     cr_plugin ctx;
     cr_plugin ctx;
-    ctx.userdata = &registry;
+    ctx.userdata = &handler;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

+ 5 - 12
test/lib/registry_plugin_std/plugin.cpp

@@ -1,28 +1,21 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/entity/registry.hpp>
 #include "types.h"
 #include "types.h"
 
 
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
 CR_EXPORT int cr_main(cr_plugin *ctx, cr_op operation) {
     switch (operation) {
     switch (operation) {
     case CR_STEP:
     case CR_STEP:
         [ctx]() {
         [ctx]() {
-            auto *registry = static_cast<entt::registry *>(ctx->userdata);
-            // forces the creation of the pool for the velocity component
-            registry->prepare<velocity>();
+            auto *proxy = static_cast<registry_proxy *>(ctx->userdata);
 
 
-            for(auto entity: registry->view<position>()) {
-                registry->assign<velocity>(entity, 1., 1.);
-            }
+            proxy->assign({1., 1.});
 
 
-            registry->view<position, velocity>().each([](auto &pos, auto &vel) {
-                pos.x += 16 * vel.dx;
-                pos.y += 16 * vel.dy;
+            proxy->for_each([](auto &pos, auto &vel) {
+                pos.x += static_cast<int>(16 * vel.dx);
+                pos.y += static_cast<int>(16 * vel.dy);
             });
             });
         }();
         }();
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
-        static_cast<entt::registry *>(ctx->userdata)->discard<velocity>();
-        break;
     case CR_LOAD:
     case CR_LOAD:
     case CR_UNLOAD:
     case CR_UNLOAD:
         // nothing to do here, this is only a test.
         // nothing to do here, this is only a test.

+ 16 - 0
test/lib/registry_plugin_std/proxy.h

@@ -0,0 +1,16 @@
+#ifndef ENTT_LIB_REGISTRY_PLUGIN_STD_PROXY_H
+#define ENTT_LIB_REGISTRY_PLUGIN_STD_PROXY_H
+
+#include <entt/entity/fwd.hpp>
+#include "types.h"
+
+struct proxy: registry_proxy {
+    proxy(entt::registry &);
+    void for_each(void(*)(position &, velocity &)) override;
+    void assign(velocity) override;
+
+private:
+    entt::registry *registry;
+};
+
+#endif

+ 5 - 22
test/lib/registry_plugin_std/types.h

@@ -1,26 +1,6 @@
 #ifndef ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
 #ifndef ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
 #define ENTT_LIB_REGISTRY_PLUGIN_STD_TYPES_H
 
 
-#include <type_traits>
-#include <entt/core/hashed_string.hpp>
-#include <entt/core/type_info.hpp>
-
-template<typename>
-struct component_id;
-
-#define ASSIGN_TYPE_ID(clazz)\
-    template<>\
-    struct component_id<clazz>\
-        : std::integral_constant<ENTT_ID_TYPE, entt::basic_hashed_string<std::remove_cv_t<std::remove_pointer_t<std::decay_t<decltype(#clazz)>>>>{#clazz}>\
-    {}
-
-template<typename Type>
-struct entt::type_info<Type> {
-    static constexpr ENTT_ID_TYPE id() ENTT_NOEXCEPT {
-        return component_id<Type>::value;
-    }
-};
-
 struct position {
 struct position {
     int x;
     int x;
     int y;
     int y;
@@ -31,7 +11,10 @@ struct velocity {
     double dy;
     double dy;
 };
 };
 
 
-ASSIGN_TYPE_ID(position);
-ASSIGN_TYPE_ID(velocity);
+struct registry_proxy {
+    virtual ~registry_proxy() = default;
+    virtual void for_each(void(*)(position &, velocity &)) = 0;
+    virtual void assign(velocity) = 0;
+};
 
 
 #endif
 #endif