Michele Caini 7 лет назад
Родитель
Сommit
24b862e32e
4 измененных файлов с 27 добавлено и 12 удалено
  1. 9 3
      README.md
  2. 8 4
      src/entt/entity/registry.hpp
  3. 7 3
      src/entt/signal/dispatcher.hpp
  4. 3 2
      src/entt/signal/sigh.hpp

+ 9 - 3
README.md

@@ -658,11 +658,17 @@ There are also some limitations on what a listener can and cannot do. In
 particular:
 particular:
 
 
 * Connecting and disconnecting other functions from within the body of a
 * Connecting and disconnecting other functions from within the body of a
-  listener should be avoided. It can lead to undefined behavior.
+  listener should be avoided. It can lead to undefined behavior in some cases.
 * Assigning and removing components and tags from within the body of a listener
 * Assigning and removing components and tags from within the body of a listener
   that observes the destruction of instances of a given type should be avoided.
   that observes the destruction of instances of a given type should be avoided.
-  It can lead to undefined behavior. This type of listeners is intended to
-  provide users with an easy way to perform cleanup and nothing more.
+  It can lead to undefined behavior in some cases. This type of listeners is
+  intended to provide users with an easy way to perform cleanup and nothing
+  more.
+
+To a certain extent, these limitations do not apply. However, it is risky to try
+to force them and users should respect the limitations unless they know exactly
+what they are doing. Subtle bugs are the price to pay in case of errors
+otherwise.
 
 
 In general, events and therefore listeners must not be used as replacements for
 In general, events and therefore listeners must not be used as replacements for
 systems. They should not contain much logic and interactions with a registry
 systems. They should not contain much logic and interactions with a registry

+ 8 - 4
src/entt/entity/registry.hpp

@@ -425,23 +425,27 @@ public:
     void destroy(entity_type entity) {
     void destroy(entity_type entity) {
         assert(valid(entity));
         assert(valid(entity));
 
 
-        std::for_each(pools.begin(), pools.end(), [entity, this](auto &&tup) {
+        for(auto pos = pools.size(); pos; --pos) {
+            auto &tup = pools[pos-1];
             auto &cpool = std::get<0>(tup);
             auto &cpool = std::get<0>(tup);
 
 
             if(cpool && cpool->has(entity)) {
             if(cpool && cpool->has(entity)) {
                 std::get<2>(tup).publish(*this, entity);
                 std::get<2>(tup).publish(*this, entity);
                 cpool->destroy(entity);
                 cpool->destroy(entity);
             }
             }
-        });
+        };
 
 
-        std::for_each(tags.begin(), tags.end(), [entity, this](auto &&tup) {
+        for(auto pos = tags.size(); pos; --pos) {
+            auto &tup = tags[pos-1];
             auto &tag = std::get<0>(tup);
             auto &tag = std::get<0>(tup);
 
 
             if(tag && tag->entity == entity) {
             if(tag && tag->entity == entity) {
                 std::get<2>(tup).publish(*this, entity);
                 std::get<2>(tup).publish(*this, entity);
                 tag.reset();
                 tag.reset();
             }
             }
-        });
+        };
+
+        assert(orphan(entity));
 
 
         const auto entt = entity & traits_type::entity_mask;
         const auto entt = entity & traits_type::entity_mask;
         const auto version = (((entity >> traits_type::entity_shift) + 1) & traits_type::version_mask) << traits_type::entity_shift;
         const auto version = (((entity >> traits_type::entity_shift) + 1) & traits_type::version_mask) << traits_type::entity_shift;

+ 7 - 3
src/entt/signal/dispatcher.hpp

@@ -168,9 +168,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.
      */
      */
     inline void update() {
     inline void update() {
-        std::for_each(wrappers.begin(), wrappers.end(), [](auto &&wrapper) {
-            return wrapper ? wrapper->publish() : void();
-        });
+        for(auto pos = wrappers.size(); pos; --pos) {
+            auto &wrapper = wrappers[pos-1];
+
+            if(wrapper) {
+                wrapper->publish();
+            }
+        }
     }
     }
 
 
 private:
 private:

+ 3 - 2
src/entt/signal/sigh.hpp

@@ -307,9 +307,10 @@ public:
      * @param args Arguments to use to invoke listeners.
      * @param args Arguments to use to invoke listeners.
      */
      */
     void publish(Args... args) {
     void publish(Args... args) {
-        std::for_each(calls.begin(), calls.end(), [&args...](auto &&call) {
+        for(auto pos = calls.size(); pos; --pos) {
+            auto &call = calls[pos-1];
             call.second(call.first, args...);
             call.second(call.first, args...);
-        });
+        }
     }
     }
 
 
     /**
     /**