util: disallow destruction of Signal from handler
refs #2313
Change-Id: Ifec8dcfe66873f88b8a39726be68f090b8c18fb3
diff --git a/src/util/signal-signal.hpp b/src/util/signal-signal.hpp
index cb9c0c4..4364d6a 100644
--- a/src/util/signal-signal.hpp
+++ b/src/util/signal-signal.hpp
@@ -56,6 +56,8 @@
Signal();
+ ~Signal();
+
/** \brief connects a handler to the signal
* \note If invoked from a handler, the new handler won't receive the current emitted signal.
* \warning The handler is permitted to disconnect itself, but it must ensure its validity.
@@ -79,6 +81,7 @@
/** \brief emits a signal
* \param args arguments passed to all handlers
* \warning Emitting the signal from a handler is undefined behavior.
+ * \warning Destructing the Signal object during signal emission is undefined behavior.
* \note If a handler throws, the exception will be propagated to the caller
* who emits this signal, and some handlers may not be executed.
*/
@@ -161,6 +164,12 @@
}
template<typename Owner, typename ...TArgs>
+Signal<Owner, TArgs...>::~Signal()
+{
+ BOOST_ASSERT(!m_isExecuting);
+}
+
+template<typename Owner, typename ...TArgs>
inline Connection
Signal<Owner, TArgs...>::connect(const Handler& handler)
{
diff --git a/tests/unit-tests/util/signal.t.cpp b/tests/unit-tests/util/signal.t.cpp
index e975cc2..41750c2 100644
--- a/tests/unit-tests/util/signal.t.cpp
+++ b/tests/unit-tests/util/signal.t.cpp
@@ -193,7 +193,7 @@
BOOST_CHECK_EQUAL(hit, 1); // handler called
BOOST_CHECK_EQUAL(connection.isConnected(), true);
- so.reset(); // destruct EventEmitter
+ so.reset(); // destruct Signal
BOOST_CHECK_EQUAL(connection.isConnected(), false);
BOOST_CHECK_NO_THROW(connection.disconnect());
}
@@ -422,21 +422,6 @@
BOOST_CHECK_EQUAL(hit, 2); // handler called
}
-BOOST_AUTO_TEST_CASE(DestructInHandler)
-{
- unique_ptr<SignalOwner0> so(new SignalOwner0());
-
- int hit = 0;
- so->sig.connect([&] {
- ++hit;
- so.reset();
- });
-
- BOOST_CHECK_NO_THROW(so->emitSignal(sig));
- BOOST_CHECK_EQUAL(hit, 1); // handler called
- BOOST_CHECK(so == nullptr);
-}
-
BOOST_AUTO_TEST_SUITE_END()
} // namespace tests