diff --git a/TODO b/TODO index c7874492b..a621f5dfc 100644 --- a/TODO +++ b/TODO @@ -5,6 +5,7 @@ * debugging tools (#60): the issue online already contains interesting tips on this, look at it * runner proposal: https://en.wikipedia.org/wiki/Fork%E2%80%93join_model https://slide-rs.github.io/specs/03_dispatcher.html * work stealing job system (see #100) + - mt scheduler based on const awareness for types * meta: sort of meta view based on meta stuff to iterate entities, void * and meta info objects * allow for built-in parallel each if possible * allow to replace std:: with custom implementations diff --git a/docs/md/signal.md b/docs/md/signal.md index 5b01a5c75..0e8a94ba9 100644 --- a/docs/md/signal.md +++ b/docs/md/signal.md @@ -201,6 +201,9 @@ signal.sink().disconnect<&foo>(); // disconnect a member function of an instance signal.sink().disconnect<&listener::bar>(&instance); +// disconnect all the member functions of an instance, if any +signal.sink().disconnect(&instance); + // discards all the listeners at once signal.sink().disconnect(); ``` @@ -289,11 +292,11 @@ dispatcher.sink().connect<&listener::method>(&listener); ``` The `disconnect` member function follows the same pattern and can be used to -selectively remove listeners: +remove one listener at a time or all of them at once: ```cpp dispatcher.sink().disconnect<&listener::receive>(&listener); -dispatcher.sink().disconnect<&listener::method>(&listener); +dispatcher.sink().disconnect(&listener); ``` The `trigger` member function serves the purpose of sending an immediate event diff --git a/src/entt/signal/sigh.hpp b/src/entt/signal/sigh.hpp index 3739289e9..6fc5a1dbe 100644 --- a/src/entt/signal/sigh.hpp +++ b/src/entt/signal/sigh.hpp @@ -213,6 +213,17 @@ public: }), calls->end()); } + /** + * @brief Disconnects member functions or free functions based on an + * instance or specific payload. + * @param value_or_instance A valid pointer that fits the purpose. + */ + void disconnect(const void *value_or_instance) { + calls->erase(std::remove_if(calls->begin(), calls->end(), [value_or_instance](const auto &delegate) { + return value_or_instance == delegate.instance(); + }), calls->end()); + } + /** * @brief Disconnects all the listeners from a signal. */ diff --git a/test/entt/signal/sigh.cpp b/test/entt/signal/sigh.cpp index 14aa48344..dbc300ff4 100644 --- a/test/entt/signal/sigh.cpp +++ b/test/entt/signal/sigh.cpp @@ -111,7 +111,7 @@ TEST(SigH, Functions) { sigh.publish(v); ASSERT_FALSE(sigh.empty()); - ASSERT_EQ(static_cast::size_type>(1), sigh.size()); + ASSERT_EQ(static_cast::size_type>(1), sigh.size()); ASSERT_EQ(42, v); v = 0; @@ -119,42 +119,47 @@ TEST(SigH, Functions) { sigh.publish(v); ASSERT_TRUE(sigh.empty()); - ASSERT_EQ(static_cast::size_type>(0), sigh.size()); + ASSERT_EQ(static_cast::size_type>(0), sigh.size()); ASSERT_EQ(v, 0); sigh.sink().connect<&sigh_listener::f>(); -} + + ASSERT_FALSE(sigh.empty()); + ASSERT_EQ(static_cast::size_type>(1), sigh.size()); + + sigh.sink().disconnect(nullptr); + + ASSERT_TRUE(sigh.empty()); + ASSERT_EQ(static_cast::size_type>(0), sigh.size());} TEST(SigH, Members) { - sigh_listener s; - sigh_listener *ptr = &s; + sigh_listener l1, l2; entt::sigh sigh; - sigh.sink().connect<&sigh_listener::g>(ptr); + sigh.sink().connect<&sigh_listener::g>(&l1); sigh.publish(42); - ASSERT_TRUE(s.k); + ASSERT_TRUE(l1.k); ASSERT_FALSE(sigh.empty()); ASSERT_EQ(static_cast::size_type>(1), sigh.size()); - sigh.sink().disconnect<&sigh_listener::g>(ptr); + sigh.sink().disconnect<&sigh_listener::g>(&l1); sigh.publish(42); - ASSERT_TRUE(s.k); + ASSERT_TRUE(l1.k); ASSERT_TRUE(sigh.empty()); ASSERT_EQ(static_cast::size_type>(0), sigh.size()); - sigh.sink().connect<&sigh_listener::g>(ptr); - sigh.sink().connect<&sigh_listener::h>(ptr); + sigh.sink().connect<&sigh_listener::g>(&l1); + sigh.sink().connect<&sigh_listener::h>(&l2); ASSERT_FALSE(sigh.empty()); ASSERT_EQ(static_cast::size_type>(2), sigh.size()); - sigh.sink().disconnect<&sigh_listener::g>(ptr); - sigh.sink().disconnect<&sigh_listener::h>(ptr); + sigh.sink().disconnect(&l1); - ASSERT_TRUE(sigh.empty()); - ASSERT_EQ(static_cast::size_type>(0), sigh.size()); + ASSERT_FALSE(sigh.empty()); + ASSERT_EQ(static_cast::size_type>(1), sigh.size()); } TEST(SigH, Collector) {