// Example class
class A : public QObject
{
Q_OBJECT
void fun() {
Timer::SingleShot(10, timerSlot); //rough code
}
public slot:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a deleted
In this case after a is deleted and timer is fired, would it execute timerSlot()? I'm getting an extremely rare crash and not sure if it's because of something fishy in this logic.
Even if the timer fires, it won't trigger the slot. The docs of ~QObject state: All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue. The only way you can trigger the A::timerSlot and delete A at the same time is if you use threads.
You are not obligated to disconnect an object's signals and slots before deleting it.
The QObject destructor will clean up obsolete signal-slot connection for you, as long as you:
Inherit from QObject
Use the Q_OBJECT macro in your class definition
Following these conventions ensures that your object emits a destroyed() signal when deleted. That's actually what Qt's signals-and-slots system uses to clean up dangling references.
You can listen to the destroyed() signal yourself if you'd like to add some debugging code to track object lifecycles.
(Depending on the particular version of Qt/moc you are using, it's quite possible that code with a non-QObject using slots, or a QObject-derived class that doesn't have Q_OBJECT in its header will still compile but cause the timerSlot() method to be invoked on a garbage pointer at runtime.)
I'm getting a extremely rare crash due to timer out of object scope which I need to fire just once. I use QTimer::singleShot which is static method and does not pertain to an instance of QTimer object which I would release with the context it fires the signal to.
That is of course solved in QTimer class and desired behavior controlled by the instance of timer class with non-static QTimer::singleShot property set to true.
// declaration
QScopedPointer<QTimer> m_timer;
protected slots:
void onTimeout();
// usage
m_timer.reset(new QTimer);
m_timer->setSingleShot(true);
QObject::connect(m_timer.data(), SIGNAL(timeout()), this, SLOT(onTimeout()));
m_timer->start(requiredTimeout);
So, no crash should happen due to timer released with the context object.
Edit: This answer was in response to the original question which did not use QObject but had class A as a standalone class inheriting nothing. The question was later edited making this answer obsolete, but I'll leave it here to show what would be needed if not using QObject.
The only way you can do that is if you keep the object alive until the timer has fired. For example:
class A : enable_shared_from_this<A> {
void fun() {
QTimer::singleShot(10, bind(&A::timerSlot, shared_from_this()));
}
public:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun();
a->reset(); // a goes out of scope, but its referent is kept alive by the `QTimer`.
The reason the above works is that you capture a shared_ptr to class A when setting the timer, and the timer will hold onto it (else it can't fire).
If you don't like or can't use recent C++ features or Boost:
struct Functor {
Functor(SharedPointer<A> a) : _a(a) {}
void operator() { a->timerSlot(); }
SharedPointer _a;
};
class A {
void fun(shared_ptr<A> self) {
QTimer::singleShot(10, Functor(self));
}
public:
void timerSlot();
}
auto a = SharedPointer<A>(new A);
a->fun(a);
To reach certainty, you can stop the timer yourself:
class A : public QObject {
QTimer t;
A() { connect(Signal-Slots); }
~A() { t.stop(); }
fun() { t.start(10); }
...
};
Related
I made a widget (QDataflowCanvas) based on QGraphicsView, where I connect the signal QGraphicsScene::selectionChanged() to the slot MainWindow::onSelectionChanged of my main window:
void MainWindow::onSelectionChanged()
{
// canvas is ptr to QDataflowCanvas, subclass of QGraphicsView
auto selNodes = canvas->selectedNodes();
auto selConns = canvas->selectedConnections();
...
}
The problem happens when I close my MainWindow and there is some item selected in the QGraphicsView.
I don't think I need to provide the complete code (although it can be found here), as I already isolated the cause of the crash.
This is what will happen (in order of causality):
destructor of MainWindow is called
destructor of QDataflowCanvas is called
destructor of QGraphicsView is called
destructor of QGraphicsScene is called, which triggers the removal of all items (with clear())
destructor of a QGraphicsItem is called
that will trigger a selectionChange event
the MainWindow::onSelectionChanged slot is called
method QDataflowCanvas::selectedNodes() is called, but the object is destroyed
crash!
which can be seen more in detail from the stack trace of the crash:
I found this workaround: if I disconnect the signal in MainWindow::~MainWindow, it will of course not crash:
MainWindow::~MainWindow()
{
QObject::disconnect(canvas->scene(), &QGraphicsScene::selectionChanged, this, &MainWindow::onSelectionChanged);
}
But this seems a rather atypical practice: I never found myself having to manually severe signal-slot connections because the program would otherwise crash.
There must be a more proper solution to this.
First of all, the name of your project is a mistake. The Q-prefixed namespace is taken. You should not be having any Q-prefixed classes in any project that uses Qt. You should rename the project to DataflowCanvas, for example.
There are three solutions:
Hold all children by value, order the children according to their dependencies. The QWidgetPrivate::deleteChildren called from QDataFlowCanvas will be a no-op, or at least it won't be touching objects you care about.
Use the old connect syntax when connecting to the MainWindow::onSelectionChanged slot. Note that when your slot was invoked, the mainwindow object was of the QWidget dynamic type, not MainWindow type. The connections made using the old connect syntax respect the dynamic type of the object, and a connection made to a slot of given class will guarantee that the object is of that class dynamically, i.e. at runtime.
Clear the selection in the destructor - then no futher selection changes will be handled.
The first solution makes everything explicit and is the one I'd use:
class DataFlowCanvas : public QGraphicsView {
...
private:
QDataflowModel *model_;
QDataflowTextCompletion *completion_;
QSet<QDataflowNode*> ownedNodes_;
QSet<QDataflowConnection*> ownedConnections_;
QMap<QDataflowModelNode*, QDataflowNode*> nodes_;
QMap<QDataflowModelConnection*, QDataflowConnection*> connections_;
bool showIOletsTooltips_;
bool showObjectHoverFeedback_;
bool showConnectionHoverFeedback_;
qreal gridSize_;
bool drawGrid_;
QGraphicsSecene scene_;
};
The scene is destructed before any other fields. Problem solved. You should hold everything else by value as well. E.g. completion_, etc. The pointer indirections are not useful.
The second solution highlights an unfortunate Qt bug. To wit -- in the code below, the old connect syntax will never invoke Derived2::aSlot2, because at the time the slot is invoked, the object isn't of the Derived2 type anymore:
#include <QtCore>
int ctr1, ctr2;
struct Derived1 : QObject {
Q_SLOT void aSlot1() { ctr1++; qDebug() << __FUNCTION__; }
Q_SIGNAL void aSignal();
~Derived1() { Q_EMIT aSignal(); }
Q_OBJECT
};
struct Derived2 : Derived1 {
Q_SLOT void aSlot2() { ctr2++; qDebug() << __FUNCTION__ << qobject_cast<Derived2*>(this); }
Q_OBJECT
};
int main() {
{
Derived2 d;
QObject::connect(&d, &Derived2::aSignal, &d, &Derived2::aSlot2);
QObject::connect(&d, SIGNAL(aSignal()), &d, SLOT(aSlot2()));
QObject::connect(&d, SIGNAL(aSignal()), &d, SLOT(aSlot1()));
}
Q_ASSERT(ctr1 == 1);
Q_ASSERT(ctr2 == 1);
}
#include "main.moc"
The output clearly demonstrates the problem:
aSlot2 QObject(0x0) <-- aSlot2 called but `this` is of `Derived1*` type!
aSlot1
I was taking it so simple :) What about just checking canvas pointer:
void MainWindow::onSelectionChanged()
{
if (!qobject_cast<QGraphicsScene*>(canvas))
return;
auto selNodes = canvas->selectedNodes();
auto selConns = canvas->selectedConnections();
...
}
I used qobject_cast to check if pointer canvas still exists. You can check in other (better) way. The code works.
QRunnable is destroyed by QThreadPool after it finishes. When I emit a signal from it and try to get the QRunnable object from slot using sender() it's NULL.
Minimal example:
// class MyRunnable : public QObject, public QRunnable
MyRunnable::run()
{
//... do some work
emit onFinished();
}
// constructor by request
MyRunnable::MyRunnable(QObject *parent) : QObject(parent),
m_someData(1),
{
}
...
private slots:
void onFinished()
{
MyRunnable* myRunnable = qobject_cast<MyRunnable*>(sender());
int val = myRunnable->getSomething(); // myRunnable is null and it crashes
}
...
// later I start it using some thread pool
MyRunnable* myRunnable = new MyRunnable;
connect(myRunnable, SIGNAL(onFinished()), this, SLOT(onFinished());
threadPool.start(myRunnable);
Is there any way I can specify when to delete this object? So I can safely access it's data members inside my slot?
You want to access your object's members after it has been destroyed. Obviously, you can't safely do that.
Plus, casting sender() to access it directly is a danger sign - both in terms of unnecessary coupling and in terms of thread safety.
Instead, you probably want to copy the relevant members into the signal:
MyRunnable::run()
{
//... do some work
emit onFinished(getSomething());
}
and simply use the results in the listener.
If you really believe you must control the lifetime of the runnable, you could observe that
the thread pool takes ownership of the runnable if runnable->autoDelete() returns true
So you could override autoDelete() to return false, then call its deleteLater() method from your slot. Take care accessing its members directly, as it is still an a thread-pool thread.
The runnable is processing a request and producing a response. Factor those out and the problem is solved:
struct FooRequest;
struct FooResponse;
using FooResponsePtr = std::shared_ptr<FooResponse>;
class Foo : public QObject, public QRunnable {
FooRequest m_req;
protected:
void run() override {
std::shared_ptr<FooResponse> rsp;
/* ... */
emit hasResponse(rsp);
}
public:
Foo(const FooRequest & req) : m_req(req) {}
Foo(FooRequest && req) : m_req(std::move(req)) {}
Q_SIGNAL void hasResponse(const FooResponsePtr &);
static void main() {
qRegisterMetatype<FooResponsePtr>();
}
};
Q_DECLARE_METATYPE(FooResponsePtr)
int main() {
Foo::main();
...
};
You could also make FooResponse an explicitly shared class using QExplicitlySharedDataPointer, making it like other cheap-to-copy Qt value classes. The access would then be direct, without a need for std::shared_ptr. The explicit sharing is cheaper than implicit sharing, and makes more sense if you don't intend to retain the copy-on-write behavior of implicit sharing.
My situation is that I have a QWidget-derived class, MyWidget, that will create a QThread-derived class (WorkerThread) to do some uninterruptible, blocking work in its run() method. The results of this are a heap-allocated instance of a QObject-derived class (DataClass) which is then received and processed by MyWidget. MyWidget is a transitory widget, though, and may be deleted while WorkerThread is still running due to user action.
Here's some pseudo-code to illustrate this:
#include <QThread>
#include <QWidget>
class DataClass : public QObject {
Q_OBJECT
public:
// contains some complex data
};
class WorkerThread : public QThread {
Q_OBJECT
public:
virtual void run() {
DataClass *result = new DataClass;
doSomeReallyLongUninterruptibleWork(result);
emit workComplete(result);
}
signals:
void workComplete(DataClass *);
};
class MyWidget : public QWidget {
Q_OBJECT
public:
void doBlockingWork() {
WorkerThread *worker = new WorkerThread;
connect(worker, &WorkerThread::finished, worker, &WorkerThread::deleteLater);
connect(worker, &WorkerThread::workComplete, this, &MyWidget::processData);
worker->start();
}
public slots:
void processData(DataClass *result) {
// Do some stuff
delete result;
// Assuming MyWidget still exists when WorkerThread has finished, no memory has leaked
}
};
Normally the correct "Qt" way to return the results of a worker thread is to have it emit a signal with its arguments being the result of its work, as illustrated above. That's fine for data that can be copied, but since the result is a pointer to a heap-allocated object, I have to be careful to make sure that memory gets freed.
And normally that wouldn't be a problem, because since WorkerThread has finished, I can safely pass the pointer to DataClass to MyWidget, have it process DataClass, and then free it.
The problem is that, as I said earlier, MyWidget is transitory and may be destroyed before WorkerThread is finishing. In this scenario, how can I ensure that the instance of DataClass gets freed one way or the other?
In particular, I'm looking for solutions that have some elegance to them, meaning that it takes advantage of Qt's features and preferably makes it so that WorkerThread maintains its separation from MyWidget so that WorkerThread doesn't need to know anything about it or any other class that might create it. I'm also open to ideas that improve upon the pattern that I'm already using.
Use smart pointer (e.g., QSharedPointer) instead a normal pointer:
DataClass *result = new DataClass;
should be replaced with
QSharedPointer<DataClass> result = QSharedPointer<DataClass>(new DataClass);
Then, you could safely pass it somewhere and do not worry about deleting it. When it is out of the last scope where it can be used, the object will be automatically destroyed.
The worker should push the result to the main thread, to indicate that it's safe to use there (per QObject semantics). The result should be auto-deleted in the main thread after everyone interested has been notified of the completion of the work. It is a minimal change:
void run() override {
auto result = new DataClass;
doSomeReallyLongUninterruptibleWork(result);
result->moveToThread(qApp->thread()); // added
emit workComplete(result);
QObject::connect(this, &QThread::finished, result, &QObject::deleteLater); // added
}
You're guaranteed that deleteLater will be invoked after the last handler of workComplete has finished in the main thread.
A single object in the main thread might wish to retain the results longer. This can be indicated by setting the parent on the result object. The object shouldn't be deleted then:
...
QObject::connect(this, &QThread::finished, result, [result]{
if (!result->parent()) result->deleteLater();
});
If you intend that multiple objects in the main thread retain the results longer, you should be using a QSharedPointer in the workComplete's argument, and you must never set the parent of the results: a non-null parent and a QSharedPointer are mutually incompatible: the former indicates a unique ownership by a parent, the latter indicates a shared ownership.
It is necessary to move the DataClass object to the main thread to avoid a race on DataClass::thead() and to allow deleteLater to work:
Worker Thread: emit workComplete(result)
Main Thread: start using result, result.thread() is the worker instance.
Worker Thread: finishes
Main Thread: result.thread() is now nullptr while the main thread is using it.
This might not be a problem, but usually indicates poor design. As soon as you start using more QObject features of DataClass, it turns the latent bug into a real bug: e.g. deleteLater won't work, timers won't work, etc.
Furthermore, destructing a QObject in any thread other than its thread is not supported. Suppose that you had your original code. The following could happen and leads to undefined behavior:
Worker Thread: emit workComplete(result)
Main Thread: start using result, result.thread() is the worker instance.
Main Thread: delete result. QObject::~QObject is invoked in qApp->thread() but result->thread() is the different, still live instance of the worker thread.
If you wish to catch such issues, add:
DataClass::~DataClass() {
Q_ASSERT(thread() == nullptr || thread() == QThread::currentThread());
...
}
It's OK to destruct a threadless object, but such objects are not fully functional: you can't deleteLater them, their timers don't work, they don't receive events, etc.
The necessity of a parent check prior to deleteLater depends on whether you intend to prolong the existence of the result past the code connected to workComplete.
The "obvious" use of a shared pointer doesn't make it clear which thread can safely access the result iff the result isn't thread-safe. It also does nothing by itself to fix the fact that once the worker finishes, the QObject is half-functional as there's no event loop associated with it. I believe that your intent is that only one thread may own the result, so that its methods don't have to be thread-safe. Luckily, QObject's semantics already express this clearly: the object's thread() is the one authorized to act on the object.
Any recipients of workComplete in the main thread will get to process the results before they vanish. If any object in the main thread wants to take ownership of the result, it can - by setting the parent. Otherwise, as soon the workComplete handlers are done, if none have claimed ownership, the result will get deleted from the main event loop.
Change the QTimer::singleShot(1000, w.data(), [&]{ w.reset(); }) timer to 2500ms to have the widget outlive the worker thread and note the difference in behavior depending on whether it claimed ownership.
Complete example:
// https://github.com/KubaO/stackoverflown/tree/master/questions/worker-shared-37956073
#include <QtCore>
struct DataClass : public QObject {
DataClass() { qDebug() << __FUNCTION__; }
~DataClass() { qDebug() << __FUNCTION__; }
};
void doSomeReallyLongUninterruptibleWork(DataClass*) { QThread::sleep(2); }
class WorkerThread : public QThread {
Q_OBJECT
public:
void run() override {
auto result = new DataClass;
doSomeReallyLongUninterruptibleWork(result);
result->moveToThread(qApp->thread());
emit workComplete(result);
QObject::connect(this, &QThread::finished, result, [result]{
if (!result->parent()) {
qDebug() << "DataClass is unclaimed and will deleteLater";
result->deleteLater();
}
});
}
Q_SIGNAL void workComplete(DataClass*);
};
class MyWidget : public QObject {
void processData(DataClass * result) {
// Do stuff with result
// Retain ownership (optional)
if (true) result->setParent(this);
}
public:
void doBlockingWork() {
auto worker = new WorkerThread;
connect(worker, &WorkerThread::workComplete, this, &MyWidget::processData);
connect(worker, &WorkerThread::finished, worker, &WorkerThread::deleteLater);
worker->start();
}
~MyWidget() { qDebug() << __FUNCTION__; }
};
int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QScopedPointer<MyWidget> w{new MyWidget};
w->doBlockingWork();
QTimer::singleShot(1000, w.data(), [&]{ w.reset(); });
QTimer::singleShot(3000, qApp, &QCoreApplication::quit);
return app.exec();
}
#include "main.moc"
You could also forgo the use of an explicit thread, and use QtConcurrent::run instead. There's no clear advantage to that, I'm showing it here just to indicate that either approach is feasible.
#include <QtConcurrent>
struct DataClass : public QObject {
Q_SIGNAL void ready();
Q_OBJECT
};
// Let's not pollute the default pool with long-running stuff
Q_GLOBAL_STATIC(QThreadPool, longPool)
class MyWidget : public QObject {
void processData(DataClass * result) {
// Do stuff with result
// Retain ownership (optional)
if (true) result->setParent(this);
}
public:
void doBlockingWork() {
auto result = new DataClass;
connect(result, &DataClass::ready, this, [=]{ MyWidget::processData(result); });
result->moveToThread(nullptr);
QtConcurrent::run(longPool, [result]{
result->moveToThread(QThread::currentThread());
doSomeReallyLongUninterruptibleWork(result);
result->moveToThread(qApp->thread());
emit result->ready();
QTimer::singleShot(0, result, [result]{
if (!result->parent()) result->deleteLater();
});
});
}
};
I am developing a C++ class library for some computing-intensive tasks (machine vision).
// I am a part of a Qt-agnostic library
class Cruncher
{
/* ... */
public:
void doStuff();
};
Then there's a Qt GUI using that library. I'm creating a worker thread to call the heavy-lifting routines from the library:
// I am a part of a Qt-based GUI which utilizes the library
class Worker : public QThread
{
/* ... */
protected:
virtual void run()
{
/* ... */
Cruncher c;
for (int i = 0; i < count; ++i)
c.doStuff(); // takes some time, and while it's working
// it should communicate status changes which should
// become visible in the GUI
}
};
Now inside doStuff() a lot happens and I want to provide some feedback to the user on what is going on without waiting for doStuff() to return. For one, maybe some finer progress reporting than just increasing the meter by one step after a each call to doStuff(). Also, doStuff() may encounter non-critical failures which let it continue a part of the work, but I'd like a message to appear in the GUI when this happens as Cruncher is working (and Worker is currently busy with a call to doStuff()).
I want the library to remain Qt-independent so I'm not willing to add signals and slots to Cruncher. Any other way to enable it to provide feedback to the GUI to report on its work when it's not a Qt class?
I was considering creating a QTimer which would poll some "status" and "errorMsg" members of Cruncher at fixed intervals while Worker is running, but this seems highly sub-optimal.
I am posting my own answer because though I took #Nim's advice, I'd like the answer to be a little more verbose and hence more useful if someone should have the same problem.
I created the skeleton of a message dispatcher in the library:
// doesn't need to know about Qt
class MessagePort
{
public:
virtual void message(std::string msg) = 0;
};
Next, I added a handle to this object to Cruncher and spiced doStuff() with occasional calls to message():
// now with Super Cow powers!
class Cruncher
{
protected:
MessagePort *msgPort_;
public:
Cruncher(MessagePort *msgPort) : msgPort_(msgPort) {}
void doStuff()
{
while(...)
{
/*...*/
msgPort_->message("Foo caused an overload in Bar!");
}
}
};
Finally, I crafted an implementation of MessagePort inside the GUI using all necessary Qt goodness:
class CruncherMsgCallback : public QObject, public MessagePort
{
Q_OBJECT
public:
CruncherMsgCallback() : QObject(), MessagePort()
{
connect(this, SIGNAL(messageSignal(const QString &)),
GUI, SLOT(messageShow(const QString &)),
Qt::QueuedConnection);
}
virtual void message(std::string msg)
{
emit messageSignal(QString::fromStdString(msg));
}
signals:
void messageSignal(const QString &msg);
};
Finally when the Worker creates an instance of Cruncher, it also gives it a pointer to a working MessagePort:
class Worker
{
protected:
virtual void run()
{
CruncherMsgCallback msgC;
Cruncher c(&msgC); // &msgC works as a pointer to a
// generic MessagePort by upcasting
c.doStuff(); // Cruncher can send messages to the GUI
// from inside doStuff()
}
};
Use a callback function (class) etc, and pass that in during construction. Things you need to report, report via that callback.
You can safely emit signals from the run() method, I think that's the best way to pass information from worker thread to the main thread. Just add the signals to your QThread subclass (avoid adding slots, if you're at all unsure how QThread threading works).
Better make the connections from these signals explicitly queued, to avoid problems. Though the default, automatic connection type should also work and do Queued signal emit, but I think it's better to be explicit in cases like this. Actually also direct signals should work as such, but then you have to take care of thread safety yourself instead of letting Qt handle it for you, and you can't connect to slots which use any of the QtGui classes which only work in the main thread, so it's better to stick to queued connections.
To pass simple information to the run() method, and if immediate reaction is not needed, maybe use a few shared QAtomicInt variables or something like that as flags, which the worker thread checks when convenient. Slightly more complex method, still requiring polling, is to have shared data structure which you protect with mutex. More complex way of communicating to that direction would involve some kind of message queue (just like Qt uses in the event loop of the main thread, when you emit signal to that direction).
I have following code:
class A : public QObject
{
Q_OBJECT
public:
A() : QObject()
{
moveToThread(&t);
t.start();
}
~A()
{
t.quit();
t.wait();
}
void doSomething()
{
QMetaObject::invokeMethod(this,"doSomethingSlot");
}
public slots:
void doSomethingSlot()
{
//do something
emit ready();
}
signals:
void ready();
private:
QThread t;
}
The question why from doSomething it must be call via QMetaObject::invokeMethod. I know that there is something with connection type. Could some one explain what is under the hood?
As you haven't specified a Qt::ConnectionType, the method will be invoked as Qt::AutoConnection, which means that it will be invoked synchronously (like a normal function call) if the object's thread affinity is to the current thread, and asynchronously otherwise. "Asynchronously" means that a QEvent is constructed and pushed onto the message queue, and will be processed when the event loop reaches it.
The reason to use QMetaObject::invokeMethod if the recipient object might be in another thread is that attempting to call a slot directly on an object in another thread can lead to corruption or worse if it accesses or modifies non-thread-safe data.
I like this trick:
void A:doSomethingSlot()
{
if (thread()!=QThread::currentThread()) {
QMetaObject::invokeMethod(this,"doSomethingSlot", Qt::QueuedConnection);
return;
}
// this is done always in same thread
...
emit ready();
}