Просмотр исходного кода

dispatcher: support enqueueing the same event type from listeners - close #1303

skypjack 1 месяц назад
Родитель
Сommit
beda424de1
2 измененных файлов с 22 добавлено и 5 удалено
  1. 4 5
      src/entt/signal/dispatcher.hpp
  2. 18 0
      test/entt/signal/dispatcher.cpp

+ 4 - 5
src/entt/signal/dispatcher.hpp

@@ -44,13 +44,12 @@ public:
           events{allocator} {}
 
     void publish() override {
-        const auto length = events.size();
+        container_type other{};
+        other.swap(events);
 
-        for(std::size_t pos{}; pos < length; ++pos) {
-            signal.publish(events[pos]);
+        for(auto &&elem: other) {
+            signal.publish(elem);
         }
-
-        events.erase(events.cbegin(), events.cbegin() + static_cast<container_type::difference_type>(length));
     }
 
     void disconnect(void *instance) override {

+ 18 - 0
test/entt/signal/dispatcher.cpp

@@ -184,6 +184,24 @@ TEST(Dispatcher, NamedQueue) {
     ASSERT_EQ(receiver.cnt, 3);
 }
 
+TEST(Dispatcher, AutoQueue) {
+    entt::dispatcher dispatcher{};
+
+    // enqueueing the same event type does not invalidate references - see #1303
+    dispatcher.sink<int>().connect<+[](entt::dispatcher &owner, int &value) {
+        for(int next{}; next < value; ++next) { owner.enqueue<int>(value); }
+    }>(dispatcher);
+
+    dispatcher.enqueue<int>(4);
+    dispatcher.update<int>();
+
+    ASSERT_EQ(dispatcher.size<int>(), 4u);
+
+    dispatcher.update<int>();
+
+    ASSERT_EQ(dispatcher.size<int>(), 16u);
+}
+
 TEST(Dispatcher, CustomAllocator) {
     const std::allocator<void> allocator{};
     entt::dispatcher dispatcher{allocator};