PDA

View Full Version : QImage thread safety



Vikram.Saralaya
10th March 2016, 06:29
Hello,

I have a camera whose generated images are stored as a QImage in my own "thread safe circular buffer".

I read that QImage is implicitly shared and hence I can access this QImage in other threads. But when I try to use QImage::scanLine to modify the buffer image, it internally calls QImage::detach and my program crashes and the debugger says QImage is invalid at this point.

I have read in so many places that there is no point in creating QSharedPointer<QImage> since internally QImage already does that.

What would be a good way to handle this? It would be great if someone can share their experience..

Regards
Vikram

anda_skoa
10th March 2016, 14:01
non-const methods "detach" if the reference count is greather than 1.
This is to ensure that the modification does not alter the "copy".

See QSharedDataPointer.

You could try detaching in the originator thread before handing the image to the other thread.

Cheers,
_

Vikram.Saralaya
10th March 2016, 15:07
I don't mind it detaching.. that's exactly what I want actually.. i.e. If my other thread is slow (and still references to QImage) the main thread should detach before modifying it. But why does it crash? Doesn't that mean QImage implicit sharing is not thread safe?


See QSharedDataPointer.
Thanks for the suggestion of QSharedPointer. So I should avoid copying QImage by value and wrap it in a shared pointer (which is something I have seen people asking to avoid because QImage is implicitly shared)?


You could try detaching in the originator thread before handing the image to the other thread.
I don't wan't to always detach and create multiple copies in the originator thread. I would expect the goal of using these shared pointers is exactly to take care of that?! Or am I missing something?

Regards
Vikram

anda_skoa
10th March 2016, 15:40
I don't mind it detaching.. that's exactly what I want actually.. i.e. If my other thread is slow (and still references to QImage) the main thread should detach before modifying it. But why does it crash? Doesn't that mean QImage implicit sharing is not thread safe?

The ref counting is thread-safe but maybe the detaching is not.



Thanks for the suggestion of QSharedPointer.

That's a different class. I linked to QSharedDataPointer because its documentation describes how the automatic detaching on modifying works as it allows one to create classes with the same behavior.



So I should avoid copying QImage by value and wrap it in a shared pointer (which is something I have seen people asking to avoid because QImage is implicitly shared)?

Using a shared pointer is a different use case, i.e. using the very same data from two places, not copying.



I don't wan't to always detach and create multiple copies in the originator thread.

What advantage do you seen in having the receiver thread do the copying?



I would expect the goal of using these shared pointers is exactly to take care of that?!
Shared pointers and implicit sharing are two very different concepts.

Cheers,
_

Vikram.Saralaya
10th March 2016, 15:57
What advantage do you seen in having the receiver thread do the copying?
My receiver thread does some image processing on the image and stores the results in the disc. The originator thread does not know how much time the processing might take. So if the processing is fast and the receiver thread can always keep up, then basically QImage is never copied/detached, which is ideal :) But for whatever reasons if the receiver can't keep up, then it should not crash, instead just start detaching and making copies. It will eventually catch up and everything will be good!

So to summarize, wrap QImage in QSharedDataPointer and passing this data pointer between threads will handle the automatic detaching only if necessary. Is that right?

anda_skoa
10th March 2016, 17:41
There is no such things as "putting something into a QSharedDataPointer".
QSharedDataPointer is a class that, together with QSharedData, can be used to implement an implicit sharing mechanism like that used by Qt itself.

Detaching happens when you have two or more variables "containing" the same image and you call a non-const method on one of these.

I assume you put the images into a list or queue and the other thread takes them from the queue.
So when you put an image into the container, just make sure that the variable is reset to a new image, e.g. an empty one, before you unlock the mutex protecting the container.
That way the only reference to the image is the container entry and no detaching will be required.

Cheers,
_