Trolltech Home | Qt-interest Home | Recent Threads | All Threads | Author | Date
All threads index page 4

Qt-interest Archive, December 2007
data transfers


Message 1 in thread

Qt!

How to transfer a lot of data from one QObject to another that live in a
different thread? 

The setup is quite like the mandelbrot example, but with the important
difference that the data should not be copied when transfering. (In the
mandelbrot the QImage object is transfered embedded in queued signals,
which means it is copied)

But here, the data that is to be transfered should not be copied! I want a
mechanism like queued signals, saying that the data is ready for read at a
given pointer address, for example.

But this means having a global buffer object. Right? Is it not a bad idea
having a global object?

And in this particular example how would one organize and protected the
global buffer? With QSemaphore? 

Merry Christmas!!
Frank

--
 [ signature omitted ] 

Message 2 in thread

Frank wrote:
> How to transfer a lot of data from one QObject to another that live in a
> different thread? 
>   

Why not emit a QByteArray by reference in a Qt::QueuedConnection? Does 
the receiving side need to write to it?

--Dave

--
 [ signature omitted ] 

Message 3 in thread

Dave Smith wrote:

> 
> Why not emit a QByteArray by reference in a Qt::QueuedConnection? Does
> the receiving side need to write to it?
> 

No, it does not need to write to it. So maybe that works.

What about deletion time of the QByteArray? Assuming the signals are queued:
Can the emmiting object delete the QByteArray right after emmiting it? Or
does the receiving object has to take care of the deletion?

Does Qt delete the object when the last reference to it is being deleted??

Frank


--
 [ signature omitted ] 

Message 4 in thread

Frank wrote:
> No, it does not need to write to it. So maybe that works.
>   

Great!

> What about deletion time of the QByteArray? Assuming the signals are queued:
> Can the emmiting object delete the QByteArray right after emmiting it? Or
> does the receiving object has to take care of the deletion?
>   

If you are using Qt::BlockingQueuedConnection (new in Qt 4.3 or so), 
then you can just wait until all the receivers are done (by virtue of 
the fact that your "emit" returned), and then clean it up in the 
emitter. If you can't use Qt::BlockingQueuedConnections, someone else 
will have to be responsible for cleaning it up, perhaps a reaper thread 
or some form of GC.

> Does Qt delete the object when the last reference to it is being deleted??
>   

Beacuse QByteArray does not inherit QObject, Qt does not track it at 
all, and does not clean it up for you in any way.

--Dave

--
 [ signature omitted ] 

Message 5 in thread

Dave Smith wrote:

> Frank wrote:
> 
>> Does Qt delete the object when the last reference to it is being
>> deleted??
>>   
> 
> Beacuse QByteArray does not inherit QObject, Qt does not track it at
> all, and does not clean it up for you in any way.
> 

What about writing a class for the transfers which inherits QObject and
implements its destructor? Like:

class PassInSignal : public QObject
{
public:
        ~PassInSignal() { delete data };
        PassInSignal(QByteArray & ba) { data = new QByteArray(ba) };
private:
        QByteArray * data;
}

Creating an object of this class will not copy the data. If this is used in
the signal, is it possible to use non blocking queued signals and delete
the object right after emmiting it??

I bother because I've got the feeling that using blocking signals is not a
choice.

Frank


--
 [ signature omitted ] 

Message 6 in thread

Frank wrote:
> What about writing a class for the transfers which inherits QObject and
> implements its destructor? Like:
>
> class PassInSignal : public QObject
> {
> public:
>         ~PassInSignal() { delete data };
>         PassInSignal(QByteArray & ba) { data = new QByteArray(ba) };
> private:
>         QByteArray * data;
> }
>
> Creating an object of this class will not copy the data. If this is used in
> the signal, is it possible to use non blocking queued signals and delete
> the object right after emmiting it??
>   

Qt will not delete that object for you either, even though it inherits 
QObject. It only auto-deletes QObjects that are children of other 
QObjects, and only when the parent QObject is deleted. In other words, 
you would still have to manage deleting it yourself.

--Dave

--
 [ signature omitted ] 

Message 7 in thread

Frank wrote:
>Dave Smith wrote:
>> Why not emit a QByteArray by reference in a Qt::QueuedConnection? Does
>> the receiving side need to write to it?
>
>No, it does not need to write to it. So maybe that works.
>
>What about deletion time of the QByteArray? Assuming the signals are
> queued: Can the emmiting object delete the QByteArray right after
> emmiting it? Or does the receiving object has to take care of the
> deletion?
>
>Does Qt delete the object when the last reference to it is being
> deleted??

Why do you have a QByteArray* in the first place?

Just pass it by const-reference or by value and it'll do the right thing.

QByteArray is one of the tool classes: reentrant, atomically ref-counted, 
implicitly shared.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 8 in thread

Thiago Macieira wrote:

> 
> Why do you have a QByteArray* in the first place?
> 
> Just pass it by const-reference or by value and it'll do the right thing.
> 
> QByteArray is one of the tool classes: reentrant, atomically ref-counted,
> implicitly shared.
> 

Just to be sure: You refer to a const reference to a "QByteArray" or a
call-by-value with a "QByteArray", right?

Using QByteArray with call-by-value in a signal will not copy the data until
the receiving side writes to the copy it gets. Is this true?? Is this the
feature of being implicitly shared?? 

Furthermore: Does the feature of being ref-counted enable the emmiting side
to delete the QByteArray right after emmiting it??

Frank

--
 [ signature omitted ] 

Message 9 in thread

Frank wrote:
> Using QByteArray with call-by-value in a signal will not copy the data until
> the receiving side writes to the copy it gets. Is this true?? Is this the
> feature of being implicitly shared?? 
>   

It's supposed to, but in my experience with QString (which supposedly 
does the same thing), it is much faster to pass by reference than by 
value, especially when dealing with large strings. My results led me to 
believe, in fact, that the implicit sharing feature in QString doesn't 
actually save you much.


> Furthermore: Does the feature of being ref-counted enable the emmiting side
> to delete the QByteArray right after emmiting it??

You don't have to delete anything if you're not dealing with pointers.

--Dave

--
 [ signature omitted ] 

Message 10 in thread

Dave Smith wrote:
>It's supposed to, but in my experience with QString (which supposedly
>does the same thing), it is much faster to pass by reference than by
>value, especially when dealing with large strings. My results led me to
>believe, in fact, that the implicit sharing feature in QString doesn't
>actually save you much.

There is a speed impact, that's true, between passing by const-reference 
and passing by value. But the impact is O(1) -- it does not matter what 
size your string is.

When you pass by value, there's an atomic increment that is done and a new 
object is created on the stack (or on the registers, depending on your 
architecture). The atomic increment can take several clock cycles to 
complete (I don't know how many).

When you pass by const-reference, all it does is pass a pointer value 
around. That's extremely fast. That's why you see everywhere in Qt code 
QStrings being passed as: const QString &.

Note, however, that some classes shouldn't be passed by reference, but 
instead by value. QLatin1String would be one of them -- but we dropped 
the ball when we made it. For Qt 5, we shall rectify that.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 11 in thread

Thiago Macieira wrote:
> There is a speed impact, that's true, between passing by const-reference 
> and passing by value. But the impact is O(1) -- it does not matter what 
> size your string is.
>   

That's not what my experience suggests. I have a bunch of code that 
passes QStrings by value over lost of signals/slots (all 
Qt::DirectConnections), and it works fast for small strings. As soon as 
large strings (like 10's of MB in size) are passed, the whole thing 
slows down considerably. I changed the signal/slot parameters to be 
pass-by-const-reference instead of pass-by-value, and didn't change 
anything else, and things went back to normal speed.

--Dave

--
 [ signature omitted ] 

Message 12 in thread

Dave Smith wrote:
>Thiago Macieira wrote:
>> There is a speed impact, that's true, between passing by
>> const-reference and passing by value. But the impact is O(1) -- it
>> does not matter what size your string is.
>
>That's not what my experience suggests. I have a bunch of code that
>passes QStrings by value over lost of signals/slots (all
>Qt::DirectConnections), and it works fast for small strings. As soon as
>large strings (like 10's of MB in size) are passed, the whole thing
>slows down considerably. I changed the signal/slot parameters to be
>pass-by-const-reference instead of pass-by-value, and didn't change
>anything else, and things went back to normal speed.

Well, I am telling you the size of the string has no impact in the 
adding-one-ref performance. (The default copy constructor or the 
assignment operator).

If you can show us the code and some performance measurements data, we can 
probably rectify the issue.

My (very, very) early guess is that you called a non-const method in your 
function, which made the QString detach and, therefore, copy the data.

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.


Message 13 in thread

Frank wrote:
>Thiago Macieira wrote:
>> Why do you have a QByteArray* in the first place?
>>
>> Just pass it by const-reference or by value and it'll do the right
>> thing.
>>
>> QByteArray is one of the tool classes: reentrant, atomically
>> ref-counted, implicitly shared.
>
>Just to be sure: You refer to a const reference to a "QByteArray" or a
>call-by-value with a "QByteArray", right?
>
>Using QByteArray with call-by-value in a signal will not copy the data
> until the receiving side writes to the copy it gets. Is this true?? Is
> this the feature of being implicitly shared??

Implicitly-shared = copy on write. If you have a QByteArray that was 
passed by value, it will not copy the data until you modify the object. 
It shares with other instances of the same data (hence "shared") and 
automatically detaches from them when you make a modification 
(hence "implicitly").

>Furthermore: Does the feature of being ref-counted enable the emmiting
> side to delete the QByteArray right after emmiting it??

Don't say "delete" because it'll lead you to think of
	delete byteArray;

That's not it. We are NOT talking about QByteArray*.

But you can let the QByteArray object go out of scope. As in:

	{
		QByteArray byteArray = ....;
		emit signal(byteArray);
	}

-- 
 [ signature omitted ] 

Attachment: signature.asc
Description: This is a digitally signed message part.