Browse Source

dispatcher: make it run smoothly across boundaries

Michele Caini 4 years ago
parent
commit
19230f7672

+ 4 - 5
docs/md/lib.md

@@ -19,8 +19,7 @@
 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
 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
 
@@ -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
   libraries or plugins.<br/>
   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
 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 <vector>
 #include "../config/config.h"
+#include "../container/dense_hash_map.hpp"
 #include "../core/fwd.hpp"
 #include "../core/type_info.hpp"
 #include "sigh.hpp"
@@ -84,17 +85,13 @@ class dispatcher {
 
     template<typename Event>
     [[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:
@@ -207,9 +204,7 @@ public:
     template<typename Type>
     void disconnect(Type *value_or_instance) {
         for(auto &&cpool: pools) {
-            if(cpool) {
-                cpool->disconnect(value_or_instance);
-            }
+            cpool.second->disconnect(value_or_instance);
         }
     }
 
@@ -225,9 +220,7 @@ public:
     void clear() {
         if constexpr(sizeof...(Event) == 0) {
             for(auto &&cpool: pools) {
-                if(cpool) {
-                    cpool->clear();
-                }
+                cpool.second->clear();
             }
         } else {
             (assure<Event>().clear(), ...);
@@ -256,15 +249,13 @@ public:
      * to reduce at a minimum the time spent in the bodies of the listeners.
      */
     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:
-    std::vector<std::unique_ptr<basic_pool>> pools;
+    dense_hash_map<id_type, std::unique_ptr<basic_pool>> pools;
 };
 
 } // namespace entt

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

@@ -2,19 +2,9 @@
 
 #include <gtest/gtest.h>
 #include <cr.h>
-#include <entt/core/type_info.hpp>
 #include <entt/signal/dispatcher.hpp>
-#include "type_context.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 {
     void on(message msg) {
         value = msg.payload;
@@ -34,9 +24,6 @@ TEST(Lib, Dispatcher) {
     cr_plugin ctx;
     cr_plugin_load(ctx, PLUGIN);
 
-    ctx.userdata = type_context::instance();
-    cr_plugin_update(ctx);
-
     ctx.userdata = &dispatcher;
     cr_plugin_update(ctx);
 

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

@@ -1,30 +1,12 @@
 #include <cr.h>
-#include <entt/core/type_info.hpp>
 #include <entt/signal/dispatcher.hpp>
-#include "type_context.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) {
     switch(operation) {
     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;
     case CR_CLOSE:
     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