5

This article detailing the "proper" use of QThread says

By the way, one extremely important thing to note here is that you should NEVER allocate heap objects (using new) in the constructor of the QObject class as this allocation is then performed on the main thread and not on the new QThread instance, meaning that the newly created object is then owned by the main thread and not the QThread instance. This will make your code fail to work. Instead, allocate such resources in the main function slot such as process() in this case as when that is called the object will be on the new thread instance and thus it will own the resource.

I understand the first part that the allocation of heap objects (and thus running a constructor) happens in the thread that created the QObject. Only after that it is pushed to the QThread using QThread::moveToThread.

However I don't quite understand the ownership issue mentioned, specifically

meaning that the newly created object is then owned by the main thread

It certainly is not referring standard ownership of resources because in Qt that can be easily controlled by parent-children mechanism.

Does it mean underlying memory management mechanisms of multithreading (or QThread although that is just a wrapper of OS' thread implementation as far as I know)? As in that there is a different "memory segment/cache" for each thread where its resources are stored?

If that is the case I could see the problem but I cannot find the full answer or explanation. Thanks!

1
  • this advice is very confusive since usually "The data and heap segments are shared by all the threads." (see this answer for example : stackoverflow.com/a/11969536/18316497). Commented Dec 3, 2024 at 15:54

1 Answer 1

9

It's referring to the fact that QObjects live in certain threads -- by default, the thread that created them. "Live" refers to the fact that QObject isn't reentrant nor thread safe: a QObject can be used only from the thread it lives in.

The advice is wrong, though. It's perfectly safe to do

class Foo : public QObject {
    Q_OBJECT
    Foo() {
        m_suboject = new Bar(this);
        m_other = new Fie("/dev/blah", this);
        ...

The key is in that this parameter, meaning the subobjects are correctly parented to the Foo instance. Hence, when you do

Foo *foo = new Foo;
foo->moveToThread(thread);

the whole object tree rooted in "foo" will be moved into the new thread (moveToThread moves an object and all its children).

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for the clarification! It makes much more sense to me now. However I do wonder, if a member object cannot have a parent (i.e. it is not a QObject subclass like some of the Qt 'primitive' classes like QString), how to ensure it is moved along with its object it belongs to? Or maybe that is a non-issue since the potential problem is only related to QObjects?
That's usually a non issue -- in that QString, unlike QObject, is reentrant: it's safe to be used from multiple threads, but only from one thread at a time.
I see, I believe I understand this completely, thank you for your time!
but it's stated differently here: wiki.qt.io/QThreads_general_usage . so why should they be wrong about this? I think is a serious issue!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.