From 24b862e32ef6549f126dc6931db13f899752adb7 Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Sun, 6 May 2018 13:58:50 +0200 Subject: [PATCH] more flexible --- README.md | 12 +++++++++--- src/entt/entity/registry.hpp | 12 ++++++++---- src/entt/signal/dispatcher.hpp | 10 +++++++--- src/entt/signal/sigh.hpp | 5 +++-- 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 547b5cd64..71e3e0e2e 100644 --- a/README.md +++ b/README.md @@ -658,11 +658,17 @@ There are also some limitations on what a listener can and cannot do. In particular: * 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 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 systems. They should not contain much logic and interactions with a registry diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index 99d72a85e..af14e428a 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -425,23 +425,27 @@ public: void destroy(entity_type 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); if(cpool && cpool->has(entity)) { std::get<2>(tup).publish(*this, 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); if(tag && tag->entity == entity) { std::get<2>(tup).publish(*this, entity); tag.reset(); } - }); + }; + + assert(orphan(entity)); 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; diff --git a/src/entt/signal/dispatcher.hpp b/src/entt/signal/dispatcher.hpp index bab85c069..62b77cfe5 100644 --- a/src/entt/signal/dispatcher.hpp +++ b/src/entt/signal/dispatcher.hpp @@ -168,9 +168,13 @@ public: * to reduce at a minimum the time spent in the bodies of the listeners. */ 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: diff --git a/src/entt/signal/sigh.hpp b/src/entt/signal/sigh.hpp index 4de63399e..6a815f7d9 100644 --- a/src/entt/signal/sigh.hpp +++ b/src/entt/signal/sigh.hpp @@ -307,9 +307,10 @@ public: * @param args Arguments to use to invoke listeners. */ 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...); - }); + } } /**