diff --git a/TODO b/TODO
index 7c09ac633..d8d9dc5fd 100644
--- a/TODO
+++ b/TODO
@@ -23,6 +23,5 @@
* cleanup - see https://github.com/skypjack/entt/commit/ad5cedc08c83e8cbcc8aaeac9634d44624ffe35a#commitcomment-32380903
==> can we do more for shared libraries? who knows... see #144
-* to be updated: dispatcher
* to be updated: emitter
* to be updated: doc
diff --git a/docs/lib.md b/docs/lib.md
index 2474743bc..3ff134830 100644
--- a/docs/lib.md
+++ b/docs/lib.md
@@ -159,9 +159,9 @@ as they are not strictly necessary.
I'm still working hard to make everything work across boundaries.
The classes affected by the problem were `registry`, `dispatcher` and `emitter`.
-Currently, only the `registry` class fully support _shared types_. Using
-`dispatcher` and `emitter` across boundaries isn't allowed yet and can result in
-unexpected behavior on Windows in general and on GNU/Linux when default
-visibility is set to _hidden_.
+Currently, only `registry` and `dispatcher` fully support _shared types_. Using
+`emitter` across boundaries isn't allowed yet and can result in unexpected
+behavior on Windows in general and on GNU/Linux when default visibility is set
+to _hidden_.
Stay tuned for future updates.
diff --git a/src/entt/signal/dispatcher.hpp b/src/entt/signal/dispatcher.hpp
index c385dd4af..749ef3b51 100644
--- a/src/entt/signal/dispatcher.hpp
+++ b/src/entt/signal/dispatcher.hpp
@@ -8,6 +8,7 @@
#include
#include "../config/config.h"
#include "../core/family.hpp"
+#include "../core/type_traits.hpp"
#include "sigh.hpp"
@@ -75,19 +76,51 @@ class dispatcher {
int current{};
};
+ struct wrapper_data {
+ std::unique_ptr wrapper;
+ ENTT_ID_TYPE runtime_type;
+ };
+
+ template
+ static auto type() ENTT_NOEXCEPT {
+ if constexpr(is_shared_v) {
+ return shared_traits::value;
+ } else {
+ return event_family::type;
+ }
+ }
+
template
signal_wrapper & wrapper() {
- const auto type = event_family::type;
+ const auto wtype = type();
+ wrapper_data *wdata = nullptr;
- if(!(type < wrappers.size())) {
- wrappers.resize(type + 1);
+ if constexpr(is_shared_v) {
+ const auto it = std::find_if(wrappers.begin(), wrappers.end(), [wtype](const auto &wdata) {
+ return wdata.wrapper && wdata.runtime_type == wtype;
+ });
+
+ wdata = (it == wrappers.cend() ? &wrappers.emplace_back() : &(*it));
+ } else {
+ if(!(wtype < wrappers.size())) {
+ wrappers.resize(wtype+1);
+ }
+
+ wdata = &wrappers[wtype];
+
+ if(wdata->wrapper && wdata->runtime_type != wtype) {
+ wrappers.emplace_back();
+ std::swap(wrappers[wtype], wrappers.back());
+ wdata = &wrappers[wtype];
+ }
}
- if(!wrappers[type]) {
- wrappers[type] = std::make_unique>();
+ if(!wdata->wrapper) {
+ wdata->wrapper = std::make_unique>();
+ wdata->runtime_type = wtype;
}
- return static_cast &>(*wrappers[type]);
+ return static_cast &>(*wdata->wrapper);
}
public:
@@ -201,16 +234,16 @@ public:
*/
inline void update(Args... args) const {
for(auto pos = wrappers.size(); pos; --pos) {
- auto &wrapper = wrappers[pos-1];
+ auto &wdata = wrappers[pos-1];
- if(wrapper) {
- wrapper->publish(args...);
+ if(wdata.wrapper) {
+ wdata.wrapper->publish(args...);
}
}
}
private:
- std::vector> wrappers;
+ std::vector wrappers;
};
diff --git a/test/entt/signal/dispatcher.cpp b/test/entt/signal/dispatcher.cpp
index 0965d716f..58a65a95a 100644
--- a/test/entt/signal/dispatcher.cpp
+++ b/test/entt/signal/dispatcher.cpp
@@ -1,9 +1,13 @@
#include
#include
+#include
#include
struct an_event {};
struct another_event {};
+struct one_more_event {};
+
+ENTT_SHARED_TYPE(an_event)
struct receiver {
void receive(const an_event &, int value) { cnt += value; }
@@ -15,9 +19,14 @@ TEST(Dispatcher, Functionalities) {
entt::dispatcher dispatcher;
receiver receiver;
+ dispatcher.trigger(1);
+ dispatcher.enqueue();
+ dispatcher.update(1);
+
dispatcher.sink().connect<&receiver::receive>(&receiver);
dispatcher.trigger(1);
dispatcher.enqueue();
+
dispatcher.enqueue();
dispatcher.update(1);