Solved Confused by Qt Object Model and QTimer
-
I'm using a QTimer as a sentinel against drop-out of data from a remote host that isn't the result of a dropped connection. The initialize() slot is tied to the started() signal from the thread in which it resides:
void TapDisplayCommunicationHandler::initialize() { heartbeat_timer = new QTimer(this); QObject::connect(heartbeat_timer, SIGNAL(timeout()), this, SLOT(handleHeartbeatTimeout())); }
Since this timer is meant to indicate when data flow stops, I don't start it until the actual connection is established:
void TapDisplayCommunicationHandler:: signalConnectionEstablished() { emit connectionEstablished(); // start "heartbeat" timer to wait for data to arrive heartbeat_timer->start(10000); }
When data arrives, I restart the timer to start the clock over:
void TapDisplayCommunicationHandler:: processIncomingData(QDataStream& input_stream) { // we've received new data before the heartbeat timer timeout. Reset thetimer heartbeat_timer->start();
If the timeout() signal hits, I emit an error to my main thread:
void TapDisplayCommunicationHandler::handleHeartbeatTimeout() { // don't allow any more timer events heartbeat_timer->stop(); // we've stopped receiving data. Emit an error signal emit connectionLost(connection_name); }
This implementation presents two problems:
-
I have to call stop() on the timer on every flavor of connection loss to prevent any more heartbeat signals
-
When/how do I delete this timer? If I call 'delete' from my destructor, the documentation says I could crash my app if there are pending events. If I want to use 'deleteLater()' what signal am I tying it to? Also, how do I delete the last instance of this timer after the event loop stops running? It seems to me the last instance will always leak if I rely on deleteLater(), since it will not execute if the event loop is stopped
-
-
Hi,
@DRoscoe said in Confused by Qt Object Model and QTimer:When/how do I delete this timer?
Well, when is up to you, as to how - use
QObject::deleteLater
. ;)If I want to use 'deleteLater()' what signal am I tying it to?
I don't follow. You can call slots as functions, because in the end they're just functions.
It seems to me the last instance will always leak if I rely on deleteLater(), since it will not execute if the event loop is stopped.
All pending delete events are processed before the event loop exits, if that's what you're asking so there's no leak (and you gave it a parent anyway, so no need to worry about the last timer).
As a side note, why don't you put the timer as an auto-storage (stack) variable in your class and just call
QTimer::start
,QTimer::stop
where appropriate. I don't see any gain in allocating it on the heap in this case.Kind regards.
-
@DRoscoe said in Confused by Qt Object Model and QTimer:
void TapDisplayCommunicationHandler::initialize() { heartbeat_timer = new QTimer(this); ... }
In the snippet above, you have set your
TapDisplayCommunicationHandler
as the parent of theQTimer
. Therefore, when you delete yourTapDisplayCommunicationHandler
, theQTimer
will automatically get deleted too. You don't need to do anything else. -
@DRoscoe said in Confused by Qt Object Model and QTimer:
I have to call stop() on the timer on every flavor of connection loss to prevent any more heartbeat signals
Looking at your code you probably want to call
heartbeat_timer->setSingleShot(true);
so it stops automatically after a timeout.@DRoscoe said in Confused by Qt Object Model and QTimer:
When/how do I delete this timer?
As mentioned already, since you pass a parent in the constructor, Qt will take care of deleting it
-
@VRonin I considered that, but it doesn't gain me much.
-
@kshegunov Thanks. I took your advice and made it a class attribute.