summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libcamera/base/object.cpp14
-rw-r--r--src/libcamera/base/signal.cpp7
-rw-r--r--test/signal.cpp17
3 files changed, 29 insertions, 9 deletions
diff --git a/src/libcamera/base/object.cpp b/src/libcamera/base/object.cpp
index 3f28768e..ec5b55d1 100644
--- a/src/libcamera/base/object.cpp
+++ b/src/libcamera/base/object.cpp
@@ -47,6 +47,14 @@ LOG_DEFINE_CATEGORY(Object)
* object's thread, regardless of whether the signal is emitted in the same or
* in another thread.
*
+ * Objects can be connected to multiple signals, but they can only be connected
+ * to each signal once. Attempting to create multiple concurrent connections
+ * between the same signal and the same Object (to either the same or differents
+ * slots of the object) will cause an assertion failure. While it would be
+ * possible to allow the implementation to let objects connect to the same
+ * signal multiple times, there are no expected use cases for this in libcamera
+ * and this behaviour is restricted to favour defensive programming.
+ *
* \sa Message, Signal, Thread
*/
@@ -284,6 +292,12 @@ void Object::notifyThreadMove()
void Object::connect(SignalBase *signal)
{
+ /*
+ * Connecting the same signal to an object multiple times is not
+ * supported.
+ */
+ ASSERT(std::find(signals_.begin(), signals_.end(), signal) == signals_.end());
+
signals_.push_back(signal);
}
diff --git a/src/libcamera/base/signal.cpp b/src/libcamera/base/signal.cpp
index 9df45d07..a46386a0 100644
--- a/src/libcamera/base/signal.cpp
+++ b/src/libcamera/base/signal.cpp
@@ -93,9 +93,7 @@ SignalBase::SlotList SignalBase::slots()
* Connecting a signal to a slot results in the slot being called with the
* arguments passed to the emit() function when the signal is emitted. Multiple
* slots can be connected to the same signal, and multiple signals can connected
- * to the same slot. Duplicate connections between a signal and a slot are
- * allowed and result in the slot being called multiple times for the same
- * signal emission.
+ * to the same slot.
*
* When a slot belongs to an instance of the Object class, the slot is called
* in the context of the thread that the object is bound to. If the signal is
@@ -105,6 +103,9 @@ SignalBase::SlotList SignalBase::slots()
* loop, after the Signal::emit() function returns, with a copy of the signal's
* arguments. The emitter shall thus ensure that any pointer or reference
* passed through the signal will remain valid after the signal is emitted.
+ *
+ * Duplicate connections between a signal and a slot are not expected and use of
+ * the Object class to manage signals will enforce this restriction.
*/
/**
diff --git a/test/signal.cpp b/test/signal.cpp
index fcf2def1..5c6b304d 100644
--- a/test/signal.cpp
+++ b/test/signal.cpp
@@ -212,17 +212,19 @@ protected:
/* ----------------- Signal -> Object tests ----------------- */
/*
- * Test automatic disconnection on object deletion. Connect the
- * slot twice to ensure all instances are disconnected.
+ * Test automatic disconnection on object deletion. Connect two
+ * signals to ensure all instances are disconnected.
*/
signalVoid_.disconnect();
+ signalVoid2_.disconnect();
SlotObject *slotObject = new SlotObject();
signalVoid_.connect(slotObject, &SlotObject::slot);
- signalVoid_.connect(slotObject, &SlotObject::slot);
+ signalVoid2_.connect(slotObject, &SlotObject::slot);
delete slotObject;
valueStatic_ = 0;
signalVoid_.emit();
+ signalVoid2_.emit();
if (valueStatic_ != 0) {
cout << "Signal disconnection on object deletion test failed" << endl;
return TestFail;
@@ -298,17 +300,19 @@ protected:
/* --------- Signal -> Object (multiple inheritance) -------- */
/*
- * Test automatic disconnection on object deletion. Connect the
- * slot twice to ensure all instances are disconnected.
+ * Test automatic disconnection on object deletion. Connect two
+ * signals to ensure all instances are disconnected.
*/
signalVoid_.disconnect();
+ signalVoid2_.disconnect();
SlotMulti *slotMulti = new SlotMulti();
signalVoid_.connect(slotMulti, &SlotMulti::slot);
- signalVoid_.connect(slotMulti, &SlotMulti::slot);
+ signalVoid2_.connect(slotMulti, &SlotMulti::slot);
delete slotMulti;
valueStatic_ = 0;
signalVoid_.emit();
+ signalVoid2_.emit();
if (valueStatic_ != 0) {
cout << "Signal disconnection on object deletion test failed" << endl;
return TestFail;
@@ -345,6 +349,7 @@ protected:
private:
Signal<> signalVoid_;
+ Signal<> signalVoid2_;
Signal<int> signalInt_;
Signal<int, const std::string &> signalMultiArgs_;