0

I have a hierarchy of classes : struct A and struct B, which is stored in an instance of A.

I run a method of A, which run a method of B, which downloads something asynchronously with connect signal of downloading to slot of B.

After that I don't use the A and B instances. They are saved in a vector.

What I need is to get information from object B about finishing of downloading (slot from B runs method A to notify it and save its data to A). After notification, the instance of B isn't needed anymore (it stores a lot of data, so I need to clear it). But no other threads know when should be done!

The thread, which calls slot B can't clear B object, because of the dangers of delete this. Even if that thread sets some mutex (which can be placed in A), and another thread, which is waiting for all time to that mutex, will delete it - it is also dangerous, because the thread of the slot can be still running.

So, how can I safely delete the B instance, within slot of B notification?

I tried to create code example here (B - downloader, A - Storage):

struct Storage
{
    Downloader *d; // createrd in ctor
    Data data; // only value, not pointer (for some reasons). 
               //The same in 'Downloader'
    int downloadedFiles; // 0 by ctor

    void run() // think, main()
    {
        d->download(); // there is an array in my program. 
                           //Here is one Downloader*, because it is example
    }

    void finishedDownload()
    {
        ++downloadedFiles;
        data = a->data;
        // delete d; // wish, it would be done like that :( 
            // But the thread will be back to a->download()
    }
}

struct Downloader
{
    Data data;
    Internet internet;
    Storage *parent;

    void download()
    {
        internet.set('http://someurl.dat');
        connect( &internet, SIGNAL(downloaded()), this, SLOT(downloaded()) );
        internet.download(&data); // async
    }

public slots :
    void downloaded()
    {
        parent->finishedDownload();
        // And there is the finish of the thread, which was created by SIGNAL of Interget,
        //but I need to delete 'Data data' from this struct.. How?
    }
};
László Papp
  • 51,870
  • 39
  • 111
  • 135
Nexen
  • 1,663
  • 4
  • 16
  • 44

1 Answers1

1

Since it's tagged qt, use this->deleteLater() instead of delete this

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • That code is not going to work with just this fix – Lol4t0 Jun 13 '14 at 15:59
  • 1
    Why not? The parent `Storage` cleans up the `Downloader`, after all it created it (see the comment on the missing ctor, logically the dtor cleans up ctor-allocated resources) – MSalters Jun 13 '14 at 16:04
  • To begin with, Using Downloader and Internet from the thread, while they belong to the main thread is probably UB. If they do belong to the thread, downloder will not work becvause event processing is not started in the thread – Lol4t0 Jun 13 '14 at 16:07
  • 1
    @Lol4t0: As far as C++ is concerned, objects don't belong to threads, so that cannot cause UB. It's true that Qt uses its main thread for event processing, and thus `downloaded()` will be called on _that_ thread. In turn, you call `deleteLater`, which again will delete the object on the Qt thread. I don't see a problem. – MSalters Jun 13 '14 at 16:16
  • 1
    Objects do belong to threads in Qt terms. And I'm pretty sure Internet class is not thread safe. And you cannot call `internet.download` from the random thread, but just from the thread internet belong to. – Lol4t0 Jun 13 '14 at 16:19