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

Qt-interest Archive, March 2008
Signal/Slot in multithreaded environment...


Message 1 in thread

I have 2 questions that may be someone can clarify. I searched on the web and 
failed to find good explanation of what is going on underneath of QT....

1.When we use Signal/Slot connection and the object sends a signal where 
paramenter is passed by reference (there is a lot of such with QString for 
example). As much as I understand the paramater should be marshalled 
(serialized) into event and the slot will be called later from event loop. 
But how qt ensures that the object referenced is still alived? especially if 
it was allocated on stack? I tried the same with sending pointer - the 
application craches ( as expected). Can someone shed a light on this issue 
(or better give a link to resources on this topic or reference to some 
books)?

2. Is there any chance that event loop will exit while it still have events to 
process. The main worry is to send from one thread a message to another with 
pointer parameter and the object pointed should be released in the targetted 
thread (let's ommit coupling of threads and not-so-good knowledge that one 
object has about it's spouse...). Any web resources will be welcomed..


Thank you in advance.
Alexander Tumarov.

--
 [ signature omitted ] 

Message 2 in thread

On Monday 17 March 2008 16:13:51 Alexander Tumarov wrote:
> I have 2 questions that may be someone can clarify. I searched on the web
> and failed to find good explanation of what is going on underneath of
> QT....
>
> 1.When we use Signal/Slot connection and the object sends a signal where
> paramenter is passed by reference (there is a lot of such with QString for
> example). As much as I understand the paramater should be marshalled
> (serialized) into event and the slot will be called later from event loop.
> But how qt ensures that the object referenced is still alived?

You're talking here about a queued connection.

If it is a direct connection, there's no marshalling/demarshalling. Quite 
simply, the slot function is called with the parameter that the signal had. 
Since all of the directly-connected slots are run inside the signal function, 
there's no problem here. Well, as long as you don't modify the parameter 
during the execution of the slots...

If it's a queued connection, on the other hand, Qt has to create a copy. It 
does that by calling QMetaType::construct(), which is nothing more than the 
low-level version of QVariant. All types that can be queued must be 
registered with QMetaType, if they are not already (see 
http://doc.trolltech.com/4.3/qvariant.html#Type-enum for types that are 
already registered)

> especially 
> if it was allocated on stack? I tried the same with sending pointer - the
> application craches ( as expected). Can someone shed a light on this issue
> (or better give a link to resources on this topic or reference to some
> books)?

Like I said above, Qt creates a copy and keeps it around until the signal is 
delivered to all slots.

The caveat is that when creating a copy of a pointer, it copies the pointer 
value, not the object pointed to.

> 2. Is there any chance that event loop will exit while it still have events
> to process. The main worry is to send from one thread a message to another
> with pointer parameter and the object pointed should be released in the
> targetted thread (let's ommit coupling of threads and not-so-good knowledge
> that one object has about it's spouse...). Any web resources will be
> welcomed..

Yes, it can happen.

The event dispatcher, when it starts, it looks at the events that are in queue 
and always delivers all of those -- except if something really bad like an 
exception occurred. At the end, it checks if the quit() function was called. 
If it was, it exits.

But note that the event dispatcher does not deliver new events: that is, 
events that were posted after it started processing. Those would be sent at 
the next iteration if the quit() function had not been called.

-- 
 [ signature omitted ] 

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


Message 3 in thread

Thank you for reply.
My coments in the body of email ...

On Monday 17 March 2008 17:28:52 Thiago Macieira wrote:
> On Monday 17 March 2008 16:13:51 Alexander Tumarov wrote:
> > I have 2 questions that may be someone can clarify. I searched on the web
> > and failed to find good explanation of what is going on underneath of
> > QT....
> >
> > 1.When we use Signal/Slot connection and the object sends a signal where
> > paramenter is passed by reference (there is a lot of such with QString
> > for example). As much as I understand the paramater should be marshalled
> > (serialized) into event and the slot will be called later from event
> > loop. But how qt ensures that the object referenced is still alived?
>
> You're talking here about a queued connection.
>
> If it is a direct connection, there's no marshalling/demarshalling. Quite
> simply, the slot function is called with the parameter that the signal had.
> Since all of the directly-connected slots are run inside the signal
> function, there's no problem here. Well, as long as you don't modify the
> parameter during the execution of the slots...
>
> If it's a queued connection, on the other hand, Qt has to create a copy. It
> does that by calling QMetaType::construct(), which is nothing more than the
> low-level version of QVariant. All types that can be queued must be
> registered with QMetaType, if they are not already (see
> http://doc.trolltech.com/4.3/qvariant.html#Type-enum for types that are
> already registered)

Yes - It is about queued connection.
So what I can understand is if the parameters passed by reference it is 
copied? 
And it then means that the only case that it is not copied is direct 
connection (that in general is preffered but not always available of course)?

>
> > especially
> > if it was allocated on stack? I tried the same with sending pointer - the
> > application craches ( as expected). Can someone shed a light on this
> > issue (or better give a link to resources on this topic or reference to
> > some books)?
>
> Like I said above, Qt creates a copy and keeps it around until the signal
> is delivered to all slots.
>
> The caveat is that when creating a copy of a pointer, it copies the pointer
> value, not the object pointed to.
>
> > 2. Is there any chance that event loop will exit while it still have
> > events to process. The main worry is to send from one thread a message to
> > another with pointer parameter and the object pointed should be released
> > in the targetted thread (let's ommit coupling of threads and not-so-good
> > knowledge that one object has about it's spouse...). Any web resources
> > will be welcomed..
>
> Yes, it can happen.
>
> The event dispatcher, when it starts, it looks at the events that are in
> queue and always delivers all of those -- except if something really bad
> like an exception occurred. At the end, it checks if the quit() function
> was called. If it was, it exits.

It is not about missing exception or like that. It is about queues for threads 
mostly. So do you mean if thread's object that runs event loop is deleted 
there is a possibility that events will be destroyed without proccessing?
If this is a case - if events from signals contain marshalled objects - does 
the framework will delete them correctly (destructors?)... then memory leaks 
can avoided by using proxies wrappers (like auto_ptr & co....).

>
> But note that the event dispatcher does not deliver new events: that is,
> events that were posted after it started processing. Those would be sent at
> the next iteration if the quit() function had not been called.


Wierd that there is no good explanation neither in books nor on trolltech site 
for these issues....I purchased both books by JBlanchette & M.Summerfield end 
either somehow missed explanations on these topics or it is just not 
there....

--
 [ signature omitted ] 

Message 4 in thread

Alexander Tumarov wrote:
>> If it's a queued connection, on the other hand, Qt has to create a
>> copy. It does that by calling QMetaType::construct(), which is nothing
>> more than the low-level version of QVariant. All types that can be
>> queued must be registered with QMetaType, if they are not already (see
>> http://doc.trolltech.com/4.3/qvariant.html#Type-enum for types that
>> are already registered)
>
>Yes - It is about queued connection.
>So what I can understand is if the parameters passed by reference it is
>copied?

Clarifying: it copies the parameter if you pass by constant reference or 
by value.

Passing by non-constant reference is like passing by pointer.

>And it then means that the only case that it is not copied is direct
>connection (that in general is preffered but not always available of
> course)?

Yes, passing by anything that is not by value in a direct connection will 
result in 0 copies. Passing by value will result in -- probably -- 1+N 
copies.

That assumes that signals and slots have the same signature. If you pass 
by const-ref in the signal by pass by value in the slot, that will 
trigger a copy.

>> The event dispatcher, when it starts, it looks at the events that are
>> in queue and always delivers all of those -- except if something
>> really bad like an exception occurred. At the end, it checks if the
>> quit() function was called. If it was, it exits.
>
>It is not about missing exception or like that. It is about queues for
> threads mostly. So do you mean if thread's object that runs event loop
> is deleted there is a possibility that events will be destroyed without
> proccessing? If this is a case - if events from signals contain
> marshalled objects - does the framework will delete them correctly
> (destructors?)... then memory leaks can avoided by using proxies
> wrappers (like auto_ptr & co....).

If you quit the thread, the event dispatcher finishes its round of 
processing and exits. Events posted *after* you called quit() will not be 
processed and will be left in the thread's event dispatcher queue.

If you then delete the thread, those events will get destroyed. Qt 
correctly cleans up any copied parameters: remember, QEvent has a virtual 
destructor, so you can catch those things.

>Wierd that there is no good explanation neither in books nor on
> trolltech site for these issues....I purchased both books by
> JBlanchette & M.Summerfield end either somehow missed explanations on
> these topics or it is just not there....

I'd consider what I've just explained completely internal implementation 
details. They're rather too advanced for the book or shouldn't be there 
because it may change.

Besides, the behaviour is what you would expect. So, unless there are 
surprises (and there aren't), there's nothing to document.

-- 
 [ signature omitted ] 

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


Message 5 in thread

On Tuesday 18 March 2008 09:01:11 Thiago Macieira wrote:
> Alexander Tumarov wrote:
> >> If it's a queued connection, on the other hand, Qt has to create a
> >> copy. It does that by calling QMetaType::construct(), which is nothing
> >> more than the low-level version of QVariant. All types that can be
> >> queued must be registered with QMetaType, if they are not already (see
> >> http://doc.trolltech.com/4.3/qvariant.html#Type-enum for types that
> >> are already registered)
> >
> >Yes - It is about queued connection.
> >So what I can understand is if the parameters passed by reference it is
> >copied?
>
> Clarifying: it copies the parameter if you pass by constant reference or
> by value.
>
> Passing by non-constant reference is like passing by pointer.


Hm.... this is pretty error-prone approach.


>
> >And it then means that the only case that it is not copied is direct
> >connection (that in general is preffered but not always available of
> > course)?
>
> Yes, passing by anything that is not by value in a direct connection will
> result in 0 copies. Passing by value will result in -- probably -- 1+N
> copies.
>
> That assumes that signals and slots have the same signature. If you pass
> by const-ref in the signal by pass by value in the slot, that will
> trigger a copy.
>
> >> The event dispatcher, when it starts, it looks at the events that are
> >> in queue and always delivers all of those -- except if something
> >> really bad like an exception occurred. At the end, it checks if the
> >> quit() function was called. If it was, it exits.
> >
> >It is not about missing exception or like that. It is about queues for
> > threads mostly. So do you mean if thread's object that runs event loop
> > is deleted there is a possibility that events will be destroyed without
> > proccessing? If this is a case - if events from signals contain
> > marshalled objects - does the framework will delete them correctly
> > (destructors?)... then memory leaks can avoided by using proxies
> > wrappers (like auto_ptr & co....).
>
> If you quit the thread, the event dispatcher finishes its round of
> processing and exits. Events posted *after* you called quit() will not be
> processed and will be left in the thread's event dispatcher queue.
>
> If you then delete the thread, those events will get destroyed. Qt
> correctly cleans up any copied parameters: remember, QEvent has a virtual
> destructor, so you can catch those things.


Thank you. 


>
> >Wierd that there is no good explanation neither in books nor on
> > trolltech site for these issues....I purchased both books by
> > JBlanchette & M.Summerfield end either somehow missed explanations on
> > these topics or it is just not there....
>
> I'd consider what I've just explained completely internal implementation
> details. They're rather too advanced for the book or shouldn't be there
> because it may change.
>
> Besides, the behaviour is what you would expect. So, unless there are
> surprises (and there aren't), there's nothing to document.

 Understanding of what is going on (at least at theoretical level) is pretty 
vital. If QT is used in a simple notepad-like projects - I agree  - the 
existing documentation is enough. But if you delve in a big complex projects 
that involves multithreading and for example complex IO (network ... local... 
whatever) - such small misunderstandings can cost a lot. Waiting for 
surprises is in general not acceptable (at least from my point of view). Of 
course I understand that "there is no bugs-free software" and that no library 
can be suited for every possible need. It is very wierd that really important 
subjects like marshalling are not explained thouroughly. 
It seems that the only way to get a proper understanding is a "usual open 
source way" - read through sources ( I am not complaining... I just hope that 
it would change - I hope QT will become more and more usable.... but 
libraries at these extents cannot evolve good without proper documentation)

I am just evaluating QT for some projects that will demand pretty complex 
multithreading and networking. 

Thank you for answering my questions.

--
 [ signature omitted ] 

Message 6 in thread

Alexander Tumarov wrote:
> Understanding of what is going on (at least at theoretical level) is
> pretty vital. If QT is used in a simple notepad-like projects - I agree
>  - the existing documentation is enough. But if you delve in a big
> complex projects that involves multithreading and for example complex
> IO (network ... local... whatever) - such small misunderstandings can
> cost a lot. Waiting for surprises is in general not acceptable (at
> least from my point of view). Of course I understand that "there is no
> bugs-free software" and that no library can be suited for every
> possible need. It is very wierd that really important subjects like
> marshalling are not explained thouroughly.
>It seems that the only way to get a proper understanding is a "usual
> open source way" - read through sources ( I am not complaining... I
> just hope that it would change - I hope QT will become more and more
> usable.... but libraries at these extents cannot evolve good without
> proper documentation)
>
>I am just evaluating QT for some projects that will demand pretty
> complex multithreading and networking.

The book will never document everything that all readers want. No book 
ever will and even all books put together won't be enough.

For one thing, the book would be incredibly thick -- both in physical 
dimensions and text quality [*]. Second, keeping up with the pace of 
development is also very difficult. I consider documenting D-Bus, 
Graphics View (4.2), QtScript (4.3), Widgets on Canvas, XmlPatterns, 
WebKit, Phonon (4.4) a lot more important than the implementation details 
of how the Qt Meta Type system works.

For another, you have all of the source code. If you want to make sure 
what the behaviour is, read the source code or run examples, tracing it 
through those functions. 

And you have mailing lists and forums. I consider this mailing list, the 
Qt Centre, etc. all part of the experience with and advantages of 
programming with Qt.

[*] I was going to say "in literal sense", but literal means "to the 
letter", which is also ambiguous in this context :-)
-- 
 [ signature omitted ] 

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


Message 7 in thread

On Tuesday 18 March 2008 10:04:21 Thiago Macieira wrote:
> Alexander Tumarov wrote:
> >ÂUnderstanding of what is going on (at least at theoretical level) is
> > pretty vital. If QT is used in a simple notepad-like projects - I agree
> > Â- the existing documentation is enough. But if you delve in a big
> > complex projects that involves multithreading and for example complex
> > IO (network ... local... whatever) - such small misunderstandings can
> > cost a lot. Waiting for surprises is in general not acceptable (at
> > least from my point of view). Of course I understand that "there is no
> > bugs-free software" and that no library can be suited for every
> > possible need. It is very wierd that really important subjects like
> > marshalling are not explained thouroughly.
> >It seems that the only way to get a proper understanding is a "usual
> > open source way" - read through sources ( I am not complaining... I
> > just hope that it would change - I hope QT will become more and more
> > usable.... but libraries at these extents cannot evolve good without
> > proper documentation)
> >
> >I am just evaluating QT for some projects that will demand pretty
> > complex multithreading and networking.
>
> The book will never document everything that all readers want. No book
> ever will and even all books put together won't be enough.
>
> For one thing, the book would be incredibly thick -- both in physical
> dimensions and text quality [*]. Second, keeping up with the pace of
> development is also very difficult. I consider documenting D-Bus,
> Graphics View (4.2), QtScript (4.3), Widgets on Canvas, XmlPatterns,
> WebKit, Phonon (4.4) a lot more important than the implementation details
> of how the Qt Meta Type system works.

Without any shadow of doubt - All of these are VERY important.
At the same time  -marshalling is always very important issue and indeed it is 
something that very important part of QT (if not of central features) is 
build upon. At list at my opinion - this topic deserves it's own part in 
documentation. 

>
> For another, you have all of the source code. If you want to make sure
> what the behaviour is, read the source code or run examples, tracing it
> through those functions.
>
> And you have mailing lists and forums. I consider this mailing list, the
> Qt Centre, etc. all part of the experience with and advantages of
> programming with Qt.

Thank you againg for your time and answers.

>
> [*] I was going to say "in literal sense", but literal means "to the
> letter", which is also ambiguous in this context :-)


--
 [ signature omitted ] 

Message 8 in thread

On Tuesday 18 March 2008 09:36:35 Alexander Tumarov wrote:
> Without any shadow of doubt - All of these are VERY important.
> At the same time Â-marshalling is always very important issue and indeed it
> is something that very important part of QT (if not of central features) is
> build upon. At list at my opinion - this topic deserves it's own part in
> documentation.

There's no marshalling. It's a simple copy (QMetaType calls your copy 
constructor).

Marshalling is used in QDataStream and in QtDBus. Both of those are optional 
features for registered meta types and both of them require that you call an 
extra function to register the marshalling (operator<<) and demarshalling 
(operator>>) functions.

All of the above is handled through template magic, macro magic and function 
pointers. It's really a hairy subject.

-- 
 [ signature omitted ] 

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


Message 9 in thread

On Tuesday 18 March 2008 11:19:40 Thiago Macieira wrote:
> On Tuesday 18 March 2008 09:36:35 Alexander Tumarov wrote:
> > Without any shadow of doubt - All of these are VERY important.
> > At the same time Â-marshalling is always very important issue and indeed
> > it is something that very important part of QT (if not of central
> > features) is build upon. At list at my opinion - this topic deserves it's
> > own part in documentation.
>
> There's no marshalling. It's a simple copy (QMetaType calls your copy
> constructor).
>

You definitelly right - not marshalling. Wrong term. Copied...
I meant that a copy of data created.

> Marshalling is used in QDataStream and in QtDBus. Both of those are
> optional features for registered meta types and both of them require that
> you call an extra function to register the marshalling (operator<<) and
> demarshalling (operator>>) functions.
>
> All of the above is handled through template magic, macro magic and
> function pointers. It's really a hairy subject.


--
 [ signature omitted ]