sigh: filter out null opaque pointers

This commit is contained in:
Michele Caini
2019-09-22 15:19:27 +02:00
parent 1edc883ca2
commit bea6f3ec14
2 changed files with 47 additions and 15 deletions

View File

@@ -339,11 +339,13 @@ public:
*/
template<auto Function>
sink before() {
sink other{*this};
auto &calls = signal->calls;
delegate<Ret(Args...)> call{};
call.template connect<Function>();
const auto &calls = signal->calls;
const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
sink other{*this};
other.offset = std::distance(it, calls.cend());
return other;
}
@@ -358,11 +360,13 @@ public:
*/
template<auto Candidate, typename Type>
sink before(Type &value_or_instance) {
sink other{*this};
auto &calls = signal->calls;
delegate<Ret(Args...)> call{};
call.template connect<Candidate>(value_or_instance);
const auto &calls = signal->calls;
const auto it = std::find(calls.cbegin(), calls.cend(), std::move(call));
sink other{*this};
other.offset = std::distance(it, calls.cend());
return other;
}
@@ -387,12 +391,16 @@ public:
*/
sink before(const void *value_or_instance) {
sink other{*this};
auto &calls = signal->calls;
const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
return delegate.instance() == value_or_instance;
});
other.offset = std::distance(it, calls.cend());
if(value_or_instance) {
const auto &calls = signal->calls;
const auto it = std::find_if(calls.cbegin(), calls.cend(), [value_or_instance](const auto &delegate) {
return delegate.instance() == value_or_instance;
});
other.offset = std::distance(it, calls.cend());
}
return other;
}
@@ -402,8 +410,7 @@ public:
*/
sink before() {
sink other{*this};
auto &calls = signal->calls;
other.offset = std::distance(calls.cbegin(), calls.cend());
other.offset = signal->calls.size();
return other;
}
@@ -503,10 +510,12 @@ public:
* @param value_or_instance An opaque pointer that fits the purpose.
*/
void disconnect(const void *value_or_instance) {
auto &calls = signal->calls;
calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
return delegate.instance() == value_or_instance;
}), calls.end());
if(value_or_instance) {
auto &calls = signal->calls;
calls.erase(std::remove_if(calls.begin(), calls.end(), [value_or_instance](const auto &delegate) {
return delegate.instance() == value_or_instance;
}), calls.end());
}
}
/*! @brief Disconnects all the listeners from a signal. */

View File

@@ -64,6 +64,11 @@ TEST_F(SigH, Clear) {
ASSERT_FALSE(sink.empty());
ASSERT_FALSE(sigh.empty());
sink.disconnect(nullptr);
ASSERT_FALSE(sink.empty());
ASSERT_FALSE(sigh.empty());
sink.disconnect();
ASSERT_TRUE(sink.empty());
@@ -166,6 +171,11 @@ TEST_F(SigH, Members) {
ASSERT_FALSE(sigh.empty());
ASSERT_EQ(2u, sigh.size());
sink.disconnect(nullptr);
ASSERT_FALSE(sigh.empty());
ASSERT_EQ(2u, sigh.size());
sink.disconnect(l1);
ASSERT_FALSE(sigh.empty());
@@ -403,6 +413,19 @@ TEST_F(SigH, BeforeOpaqueInstanceOrPayload) {
ASSERT_EQ(functor.value, 6);
}
TEST_F(SigH, BeforeNullOpaqueInstanceOrPayload) {
entt::sigh<void(int)> sigh;
entt::sink sink{sigh};
before_after functor;
sink.connect<&before_after::static_mul>(functor);
sink.connect<&before_after::add>(functor);
sink.before(nullptr).connect<&before_after::static_add>();
sigh.publish(2);
ASSERT_EQ(functor.value, 4);
}
TEST_F(SigH, BeforeAnythingElse) {
entt::sigh<void(int)> sigh;
entt::sink sink{sigh};