Solved prohibiting duplicate connections?
-
I had been wondering for some time about how the slot connections were implemented so I reviewed the QObject connect and disconnect code the other day. I was particularly interested in any safeguards to keep from making redundant connections. I noted that UniqueConnection is an option, but not for functors, lambdas, or signals/slots in different threads. I'm wondering why...
Seems like a unique hash map of each attemption connect() would be a no-brainer, and could allow prohibiting multiple redundant connections for all of the cases where they are not currently supported.
Anyone claim to know the mind of the developers, and why UniqueConnection is not supported for all connect() calls?
Just curious
-
Hi,
There are overloads for that, see for example this one here.
As for the threads involvement, they have nothing to do with unique connections.
[Edit: SGaist] Incomplete answer as I mainly focused on the thread aspect.
-
The inline code documentation for 5.12.1 states that UniqueConnection is not supported in the cases I outlined above. That's my quandry...why?...What am I missing, that kept the devs from fully utilizing the UniqueConnection parameter?
qtbase/src/corelib/kernel/qobject.cpp: line 2653
// \note Qt::UniqueConnections do not work for lambdas, non-member functions and functors; they only apply to connecting to member functions.
-
@SGaist said in prohibiting duplicate connections?:
Hi,
There are overloads for that, see for example this one here.
As for the threads involvement, they have nothing to do with unique connections.
The link given by @SGaist here has this note as well
Note: Qt::UniqueConnections do not work for lambdas, non-member functions and functors; they only apply to connecting to member functions. -
@Kent-Dorfman
Hi
lambas are pr nature anonymous and UniqueConnections uses the metasystem from QObject
so i would guess on they thought it too involving to support 2 systems. -
@Kent-Dorfman said in prohibiting duplicate connections?:
That's my quandry...why?...What am I missing, that kept the devs from fully utilizing the UniqueConnection parameter?
The quick answer is that you can't distinguish a lambda from the same lambda. Think of a lambda (and a functor) as an object, so while two instances of the same (anonymous) class may do the same, they are still distinct objects.
-
Does it help to see if it is connected at all:
bool isSignalConnected(const QMetaMethod &signal) const int receivers(const char *signal) const
https://doc.qt.io/qt-5.12/qobject.html#protected-functions
This won't help if you need more than one connection of different slots/signals though. Too bad there isn't a way to check if a particular connection has been made. You may need to monitor this yourself with a wrapper. Probably won't help with lambdas though. -
Well, it looks like there are no easy answers to this. Certainly, a wrapper at the application level is less desirable than seeing it better implemented in the framework...aside from lambdas and functors, seems that any other "defined" function should fit easily into the lookup table scheme, but the devs didn't go that route.
Probably no sense in further discussion.
-
I think you should ask this question on the Development mailing list. The developers can tell you better, why this limitations exist and if there is a chance to change it. (If you do, please post a link to the archive afterwards, you can reach it from the link above - thanks).
Probably no sense in further discussion.
At least not here, because we don't know the deep details.
Regards
-
At least not here, because we don't know the deep details.
It's a twofold problem:
- The
connect
needs a contextQObject
, if not specified that's the sender.
Then the question becomes is the following the same connection:
QObject * otherObject; void freeFunction(); QObject::connect(this, &MyClass::someSignal, otherObject, freeFunction); QObject::connect(this, &MyClass::someSignal, this, freeFunction);
where, conceivably, otherObject may be in a different thread. Nobody knows how these two should be distinguished exactly - in some cases they may be considered the same, in some they may not.
freeFunction
isn't attached to the class ofthis
, nor to the class ofotherObject
.- A functor (a.k.a. lamda, a.k.a. function object, std::function, etc.) more often than not has (internal) state. So two instances of the same type (i.e. two lambdas) can't be distinguished due to the fact that the state is not known to Qt. Example:
auto functor1 = [this] () -> void { qDebug() << "Functor"; } auto functor2 = functor1; //< Object copy here! We are dealing with another entity entirely! QObject::connect(this, &MyClass::someSignal, this, functor1); QObject::connect(this, &MyClass::someSignal, this, functor2); //< functor2 isn't functor1
And to add insult to injury:
QObject::connect(this, &MyClass::someSignal, this, functor1); //< Object copy of functor1! QObject::connect(this, &MyClass::someSignal, this, functor1); //< Object copy of functor1, again!
- The