Преглед изворни кода

dispatcher: make it run smoothly across boundaries

Michele Caini пре 4 година
родитељ
комит
19230f7672

+ 4 - 5
docs/md/lib.md

@@ -19,8 +19,7 @@
 general and on GNU/Linux when default visibility was set to hidden. The
 general and on GNU/Linux when default visibility was set to hidden. The
 limitation was mainly due to a custom utility used to assign unique, sequential
 limitation was mainly due to a custom utility used to assign unique, sequential
 identifiers with different types.<br/>
 identifiers with different types.<br/>
-Fortunately, nowadays using `EnTT` across boundaries is easier. However, use in
-standalone applications is favored and user intervention is otherwise required.
+Fortunately, nowadays using `EnTT` across boundaries is much easier.
 
 
 ## The EnTT way
 ## The EnTT way
 
 
@@ -54,9 +53,9 @@ In general, these classes don't arouse much interest. The only exceptions are:
   that is also shared between the main application and the dynamically loaded
   that is also shared between the main application and the dynamically loaded
   libraries or plugins.<br/>
   libraries or plugins.<br/>
   This will make the type system available to the whole application, not just to
   This will make the type system available to the whole application, not just to
-  a particular tool such as the registry or the dispatcher. It means that a call
-  to `type_index::value()` will return the same identifier for the same type
-  from both sides of a boundary and can be used reliably for any purpose.
+  a particular tool such as the registry. It means that a call to
+  `type_index::value()` will return the same identifier for the same type from
+  both sides of a boundary and can be used reliably for any purpose.
 
 
 For anyone who needs more details, the test suite contains multiple examples
 For anyone who needs more details, the test suite contains multiple examples
 covering the most common cases (see the `lib` directory for all details).<br/>
 covering the most common cases (see the `lib` directory for all details).<br/>

+ 12 - 21
src/entt/signal/dispatcher.hpp

@@ -7,6 +7,7 @@
 #include <utility>
 #include <utility>
 #include <vector>
 #include <vector>
 #include "../config/config.h"
 #include "../config/config.h"
+#include "../container/dense_hash_map.hpp"
 #include "../core/fwd.hpp"
 #include "../core/fwd.hpp"
 #include "../core/type_info.hpp"
 #include "../core/type_info.hpp"
 #include "sigh.hpp"
 #include "sigh.hpp"
@@ -84,17 +85,13 @@ class dispatcher {
 
 
     template<typename Event>
     template<typename Event>
     [[nodiscard]] pool_handler<Event> &assure() {
     [[nodiscard]] pool_handler<Event> &assure() {
-        const auto index = type_index<Event>::value();
-
-        if(!(index < pools.size())) {
-            pools.resize(std::size_t(index) + 1u);
-        }
-
-        if(!pools[index]) {
-            pools[index].reset(new pool_handler<Event>{});
+        if(auto &&ptr = pools[type_id<Event>().hash()]; !ptr) {
+            auto *cpool = new pool_handler<Event>{};
+            ptr.reset(cpool);
+            return *cpool;
+        } else {
+            return static_cast<pool_handler<Event> &>(*ptr);
         }
         }
-
-        return static_cast<pool_handler<Event> &>(*pools[index]);
     }
     }
 
 
 public:
 public:
@@ -207,9 +204,7 @@ public:
     template<typename Type>
     template<typename Type>
     void disconnect(Type *value_or_instance) {
     void disconnect(Type *value_or_instance) {
         for(auto &&cpool: pools) {
         for(auto &&cpool: pools) {
-            if(cpool) {
-                cpool->disconnect(value_or_instance);
-            }
+            cpool.second->disconnect(value_or_instance);
         }
         }
     }
     }
 
 
@@ -225,9 +220,7 @@ public:
     void clear() {
     void clear() {
         if constexpr(sizeof...(Event) == 0) {
         if constexpr(sizeof...(Event) == 0) {
             for(auto &&cpool: pools) {
             for(auto &&cpool: pools) {
-                if(cpool) {
-                    cpool->clear();
-                }
+                cpool.second->clear();
             }
             }
         } else {
         } else {
             (assure<Event>().clear(), ...);
             (assure<Event>().clear(), ...);
@@ -256,15 +249,13 @@ public:
      * to reduce at a minimum the time spent in the bodies of the listeners.
      * to reduce at a minimum the time spent in the bodies of the listeners.
      */
      */
     void update() const {
     void update() const {
-        for(auto pos = pools.size(); pos; --pos) {
-            if(auto &&cpool = pools[pos - 1]; cpool) {
-                cpool->publish();
-            }
+        for(auto &&cpool: pools) {
+            cpool.second->publish();
         }
         }
     }
     }
 
 
 private:
 private:
-    std::vector<std::unique_ptr<basic_pool>> pools;
+    dense_hash_map<id_type, std::unique_ptr<basic_pool>> pools;
 };
 };
 
 
 } // namespace entt
 } // namespace entt

+ 0 - 13
test/lib/dispatcher_plugin/main.cpp

@@ -2,19 +2,9 @@
 
 
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 #include <cr.h>
 #include <cr.h>
-#include <entt/core/type_info.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/dispatcher.hpp>
-#include "type_context.h"
 #include "types.h"
 #include "types.h"
 
 
-template<typename Type>
-struct entt::type_index<Type> {
-    [[nodiscard]] static id_type value() ENTT_NOEXCEPT {
-        static const entt::id_type value = type_context::instance()->value(entt::type_hash<Type>::value());
-        return value;
-    }
-};
-
 struct listener {
 struct listener {
     void on(message msg) {
     void on(message msg) {
         value = msg.payload;
         value = msg.payload;
@@ -34,9 +24,6 @@ TEST(Lib, Dispatcher) {
     cr_plugin ctx;
     cr_plugin ctx;
     cr_plugin_load(ctx, PLUGIN);
     cr_plugin_load(ctx, PLUGIN);
 
 
-    ctx.userdata = type_context::instance();
-    cr_plugin_update(ctx);
-
     ctx.userdata = &dispatcher;
     ctx.userdata = &dispatcher;
     cr_plugin_update(ctx);
     cr_plugin_update(ctx);
 
 

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

@@ -1,30 +1,12 @@
 #include <cr.h>
 #include <cr.h>
-#include <entt/core/type_info.hpp>
 #include <entt/signal/dispatcher.hpp>
 #include <entt/signal/dispatcher.hpp>
-#include "type_context.h"
 #include "types.h"
 #include "types.h"
 
 
-struct ctx {
-    inline static type_context *ref;
-};
-
-template<typename Type>
-struct entt::type_index<Type> {
-    [[nodiscard]] static id_type value() ENTT_NOEXCEPT {
-        static const entt::id_type value = ctx::ref->value(entt::type_hash<Type>::value());
-        return value;
-    }
-};
-
 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:
-        if(!ctx::ref) {
-            ctx::ref = static_cast<type_context *>(ctx->userdata);
-        } else {
-            static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
-            static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
-        }
+        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<event>();
+        static_cast<entt::dispatcher *>(ctx->userdata)->trigger<message>(42);
         break;
         break;
     case CR_CLOSE:
     case CR_CLOSE:
     case CR_LOAD:
     case CR_LOAD:

+ 0 - 28
test/lib/dispatcher_plugin/type_context.h

@@ -1,28 +0,0 @@
-#ifndef ENTT_LIB_DISPATCHER_PLUGIN_TYPE_CONTEXT_H
-#define ENTT_LIB_DISPATCHER_PLUGIN_TYPE_CONTEXT_H
-
-#include <unordered_map>
-#include <entt/core/fwd.hpp>
-
-class type_context {
-    type_context() = default;
-
-public:
-    inline entt::id_type value(const entt::id_type name) {
-        if(name_to_index.find(name) == name_to_index.cend()) {
-            name_to_index[name] = entt::id_type(name_to_index.size());
-        }
-
-        return name_to_index[name];
-    }
-
-    static type_context *instance() {
-        static type_context self{};
-        return &self;
-    }
-
-private:
-    std::unordered_map<entt::id_type, entt::id_type> name_to_index{};
-};
-
-#endif