Qt-interest Archive, June 2007
Confusion with Qt's Threads model
Message 1 in thread
Hello list,
To some degree, my confusion comes when comparing my previous
understanding of Threads in general, with the model that is described
in Qt... I am reading books that describe threads and processes (such
as PThreads Programming, O'Reily ... and Operating System Concepts,
Wiley) and sometimes struggling to see consistency between those
models and what Qt describes.. However, I keep re-reading the Qt docs
and pick things up here and there, but sometimes I feel I am possibly
missing some important point.. so I would appreciate any feedback on
my analysis
The Qt documentations say that objects "live" in a particular thread.
But I thought that all global data and heap memory are shared by all
threads.. I thought that threads essentially have access to all these
data objects.. so why do objects in Qt have this "ownership" concept?
And one important thing... when we talk about an object belonging to a
particular thread, are we talking about those objects living in the
heap, data segment, or in the thread's stack?... The whole idea of
object ownership makes sense if we are talking about the objects
created on the thread's stack.. but why can't different threads access
objects if they are on the heap? (assuming we correctly synchronise
access to them of course).. Because I thought that all threads in the
same process share the same heap and data segment - but they each have
their own stack.
I do understand how threads can have their own event loop. Is it
because of this that we need the notion of ownership?
I have also been reading the article in the latest Linux Journal about
"Asynchronous Database Access with Qt 4.x".. It talks about this -
stating ownership, etc, but I still do not understand "why" it must be
respected.. I understood most of the article, except the part when it
talks about objects "living" in a thread... Just like the Qt docs..
Is this a Qt thing? I would appreciate some comments or if you
recommend some further reading that will help make this clearer, I
would greatly appreciate your time. For now, I will keep researching
this so as I clarify things.
Also, when we talk about executing in the context of a particular
thread, what exactly does this mean? .. What makes the context of a
thread? I thought it's just the stack and registers (program counter,
stack pointer, etc)
Thank you.
Regards,
Nasser
--
[ signature omitted ]
Message 2 in thread
I would highly recommend watching Brad's presentation on Qt's threading
model.
http://trolltech.com/company/newsroom/events/allevents/devdays2006/videolinks
Oh wait, the link on the site is broken. I will poke the right people to
get it back up :)
Girish
Nasser wrote:
> Hello list,
>
> To some degree, my confusion comes when comparing my previous
> understanding of Threads in general, with the model that is described
> in Qt... I am reading books that describe threads and processes (such
> as PThreads Programming, O'Reily ... and Operating System Concepts,
> Wiley) and sometimes struggling to see consistency between those
> models and what Qt describes.. However, I keep re-reading the Qt docs
> and pick things up here and there, but sometimes I feel I am possibly
> missing some important point.. so I would appreciate any feedback on
> my analysis
>
> The Qt documentations say that objects "live" in a particular thread.
> But I thought that all global data and heap memory are shared by all
> threads.. I thought that threads essentially have access to all these
> data objects.. so why do objects in Qt have this "ownership" concept?
>
> And one important thing... when we talk about an object belonging to a
> particular thread, are we talking about those objects living in the
> heap, data segment, or in the thread's stack?... The whole idea of
> object ownership makes sense if we are talking about the objects
> created on the thread's stack.. but why can't different threads access
> objects if they are on the heap? (assuming we correctly synchronise
> access to them of course).. Because I thought that all threads in the
> same process share the same heap and data segment - but they each have
> their own stack.
>
> I do understand how threads can have their own event loop. Is it
> because of this that we need the notion of ownership?
>
> I have also been reading the article in the latest Linux Journal about
> "Asynchronous Database Access with Qt 4.x".. It talks about this -
> stating ownership, etc, but I still do not understand "why" it must be
> respected.. I understood most of the article, except the part when it
> talks about objects "living" in a thread... Just like the Qt docs..
>
> Is this a Qt thing? I would appreciate some comments or if you
> recommend some further reading that will help make this clearer, I
> would greatly appreciate your time. For now, I will keep researching
> this so as I clarify things.
>
> Also, when we talk about executing in the context of a particular
> thread, what exactly does this mean? .. What makes the context of a
> thread? I thought it's just the stack and registers (program counter,
> stack pointer, etc)
>
> Thank you.
>
> Regards,
> Nasser
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
--
[ signature omitted ]
Message 3 in thread
Girish Ramakrishnan wrote:
> I would highly recommend watching Brad's presentation on Qt's threading
> model.
> http://trolltech.com/company/newsroom/events/allevents/devdays2006/videolinks
>
>
> Oh wait, the link on the site is broken. I will poke the right people to
> get it back up :)
Videos are online now.
Girish
--
[ signature omitted ]
Message 4 in thread
On Wednesday 06 June 2007 04:31:09 Nasser wrote:
> Hello list,
>
> To some degree, my confusion comes when comparing my previous
> understanding of Threads in general, with the model that is described
> in Qt... I am reading books that describe threads and processes (such
> as PThreads Programming, O'Reily ... and Operating System Concepts,
> Wiley) and sometimes struggling to see consistency between those
> models and what Qt describes.. However, I keep re-reading the Qt docs
> and pick things up here and there, but sometimes I feel I am possibly
> missing some important point.. so I would appreciate any feedback on
> my analysis
>
> The Qt documentations say that objects "live" in a particular thread.
> But I thought that all global data and heap memory are shared by all
> threads.. I thought that threads essentially have access to all these
> data objects.. so why do objects in Qt have this "ownership" concept?
Remember, the documentation refers to QObjects only. Every QObject has
affinity to a particular thread (this is what QObject::thread() returns).
This affinity (or ownership) tells us 1) which thread the QObject was created
in, 2) which thread we're going to use the QObject from, and 3) which thread
delivers events to the QObject.
We aren't changing the multi-threading model at all; the complete address
space is visible and available to all threads, just like in the books you've
been reading.
There are a number of reasons why we do this:
1. To define how QObjects will receive events.
2. To allow signal-slot connections without explicit locking in the
emitting/slot code.
3. To make it even more obvious that most QObject subclasses are not
thread-safe (especially I/O classes, which are all essentially state
machines).
> And one important thing... when we talk about an object belonging to a
> particular thread, are we talking about those objects living in the
> heap, data segment, or in the thread's stack?... The whole idea of
> object ownership makes sense if we are talking about the objects
> created on the thread's stack.. but why can't different threads access
> objects if they are on the heap? (assuming we correctly synchronise
> access to them of course).. Because I thought that all threads in the
> same process share the same heap and data segment - but they each have
> their own stack.
Thread affinity is not meant to convey any kind of ownership. The
documentation seems to be a bit misleading, I'll see if I can correct that.
> I do understand how threads can have their own event loop. Is it
> because of this that we need the notion of ownership?
This is why we need the notion of thread affinity, yes. Ownership is something
else, and handled in other ways (by parents taking ownership of child or
placing objects on the stack).
> I have also been reading the article in the latest Linux Journal about
> "Asynchronous Database Access with Qt 4.x".. It talks about this -
> stating ownership, etc, but I still do not understand "why" it must be
> respected.. I understood most of the article, except the part when it
> talks about objects "living" in a thread... Just like the Qt docs..
Think of it like a team or project inside of a larger department. Everyone in
the department is associated with a team or project, and the team operates
independenty from the other teams (mostly). It's this type of association
that QObject::thread() mimics. Changing "teams" is something that often
happens, and QObject can do it too (see QObject::moveToThread()).
> Is this a Qt thing? I would appreciate some comments or if you
> recommend some further reading that will help make this clearer, I
> would greatly appreciate your time. For now, I will keep researching
> this so as I clarify things.
>
> Also, when we talk about executing in the context of a particular
> thread, what exactly does this mean? .. What makes the context of a
> thread? I thought it's just the stack and registers (program counter,
> stack pointer, etc)
You almost answered your own question :)
A thread context is the stack and register state, and saying "executing in the
context of a particular thread" is the same as saying "executing in a
particular thread."
--
[ signature omitted ]
Message 5 in thread
Bradley,
I've done alot of thread programming. QT threads confuse me as well
and I often feel like I am hacking the thread object to match my
reality.
In traditional thread programming, I pass an entry point to a routine
that I want run. QThread has a pure virtual, "Run". I can write my
run and do some looping that does some work. I never release control
of that loop. In the examples, I see they set some things up and
then call exec(). What I have never been able to bridge is at what
point do I get control back to my thread.
Consider this:
Producer thread -> Linked list with a QMutex Lock -> picked up by a
consumer thread.
My hacks have been, and I've seem many others do the same,
// a consumer thread may contain the following..
while (running)
{
if (list.size())
{
anObject = list.front();
// do some work
list.pop_front();
}
sleep(1);
}
The docs and examples are such that I'm don't feel comfortable
breaking away from this.
If I just call exec and my run returns, how do I get any work done?
Also, on this subject, can Trolltech build a true cross platform
system object? QMutex is implemented using process objects and is
not a true system wide lock. This is necessary when software is
built as a collection of executables and not threads.
Michael
On Jun 5, 2007, at 11:34 PM, Bradley T Hughes wrote:
> On Wednesday 06 June 2007 04:31:09 Nasser wrote:
>> Hello list,
>>
>> To some degree, my confusion comes when comparing my previous
>> understanding of Threads in general, with the model that is described
>> in Qt... I am reading books that describe threads and processes (such
>> as PThreads Programming, O'Reily ... and Operating System Concepts,
>> Wiley) and sometimes struggling to see consistency between those
>> models and what Qt describes.. However, I keep re-reading the Qt docs
>> and pick things up here and there, but sometimes I feel I am possibly
>> missing some important point.. so I would appreciate any feedback on
>> my analysis
>>
>> The Qt documentations say that objects "live" in a particular thread.
>> But I thought that all global data and heap memory are shared by all
>> threads.. I thought that threads essentially have access to all these
>> data objects.. so why do objects in Qt have this "ownership" concept?
>
> Remember, the documentation refers to QObjects only. Every QObject has
> affinity to a particular thread (this is what QObject::thread()
> returns).
> This affinity (or ownership) tells us 1) which thread the QObject
> was created
> in, 2) which thread we're going to use the QObject from, and 3)
> which thread
> delivers events to the QObject.
>
> We aren't changing the multi-threading model at all; the complete
> address
> space is visible and available to all threads, just like in the
> books you've
> been reading.
>
> There are a number of reasons why we do this:
> 1. To define how QObjects will receive events.
> 2. To allow signal-slot connections without explicit locking in the
> emitting/slot code.
> 3. To make it even more obvious that most QObject subclasses are not
> thread-safe (especially I/O classes, which are all essentially state
> machines).
>
>> And one important thing... when we talk about an object belonging
>> to a
>> particular thread, are we talking about those objects living in the
>> heap, data segment, or in the thread's stack?... The whole idea of
>> object ownership makes sense if we are talking about the objects
>> created on the thread's stack.. but why can't different threads
>> access
>> objects if they are on the heap? (assuming we correctly synchronise
>> access to them of course).. Because I thought that all threads in the
>> same process share the same heap and data segment - but they each
>> have
>> their own stack.
>
> Thread affinity is not meant to convey any kind of ownership. The
> documentation seems to be a bit misleading, I'll see if I can
> correct that.
>
>> I do understand how threads can have their own event loop. Is it
>> because of this that we need the notion of ownership?
>
> This is why we need the notion of thread affinity, yes. Ownership
> is something
> else, and handled in other ways (by parents taking ownership of
> child or
> placing objects on the stack).
>
>> I have also been reading the article in the latest Linux Journal
>> about
>> "Asynchronous Database Access with Qt 4.x".. It talks about this -
>> stating ownership, etc, but I still do not understand "why" it
>> must be
>> respected.. I understood most of the article, except the part when it
>> talks about objects "living" in a thread... Just like the Qt docs..
>
> Think of it like a team or project inside of a larger department.
> Everyone in
> the department is associated with a team or project, and the team
> operates
> independenty from the other teams (mostly). It's this type of
> association
> that QObject::thread() mimics. Changing "teams" is something that
> often
> happens, and QObject can do it too (see QObject::moveToThread()).
>
>> Is this a Qt thing? I would appreciate some comments or if you
>> recommend some further reading that will help make this clearer, I
>> would greatly appreciate your time. For now, I will keep researching
>> this so as I clarify things.
>>
>> Also, when we talk about executing in the context of a particular
>> thread, what exactly does this mean? .. What makes the context of a
>> thread? I thought it's just the stack and registers (program
>> counter,
>> stack pointer, etc)
>
> You almost answered your own question :)
>
> A thread context is the stack and register state, and saying
> "executing in the
> context of a particular thread" is the same as saying "executing in a
> particular thread."
>
> --
> Bradley T. Hughes - bhughes at trolltech.com
> Trolltech ASA - Sandakervn. 116, P.O. Box 4332 Nydalen, 0402 Oslo,
> Norway
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx
> with "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
--
[ signature omitted ]
Message 6 in thread
Michael Simpson wrote:
> Bradley,
> I've done alot of thread programming. QT threads confuse me as well
> and I often feel like I am hacking the thread object to match my reality.
>
> In traditional thread programming, I pass an entry point to a routine
> that I want run. QThread has a pure virtual, "Run". I can write my
> run and do some looping that does some work. I never release control
> of that loop. In the examples, I see they set some things up and then
> call exec(). What I have never been able to bridge is at what point
> do I get control back to my thread.
>
> Consider this:
>
> Producer thread -> Linked list with a QMutex Lock -> picked up by a
> consumer thread.
>
> My hacks have been, and I've seem many others do the same,
>
> // a consumer thread may contain the following..
> while (running)
> {
> if (list.size())
> {
> anObject = list.front();
> // do some work
> list.pop_front();
> }
> sleep(1);
> }
>
Look into QWaitCondition. Have the consumer do as much work as possible
(maybe clear the work queue) and then wait() on a QWaitCondition when
the queue is empty. This will sleep your thread. Make sure the producers
call waitCondition.wakeOne() or waitCondition.wakeAll() when inserting
into the queue. This will wake up your thread. I suggest to take a look
at the bounded buffer example in the latest Qt Quarterly.
--Justin
begin:vcard
begin:vcard
fn:Justin Noel
n:Noel;Justin
org:ICS;Engineering
adr:;;54B Middlesex Trpk;Bedford;MA;01730;USA
email;internet:justin@xxxxxxx
title:Sr. Consulting Engineer / Certified Qt Instructor
tel;work:(617) 621-0060
url:http://www.ics.com
version:2.1
end:vcard
Message 7 in thread
On 06.06.07 10:18:14, Michael Simpson wrote:
> Bradley,
> I've done alot of thread programming. QT threads confuse me as well and I
> often feel like I am hacking the thread object to match my reality.
>
> In traditional thread programming, I pass an entry point to a routine that I
> want run. QThread has a pure virtual, "Run". I can write my run and do some
> looping that does some work. I never release control of that loop. In the
> examples, I see they set some things up and then call exec(). What I have
> never been able to bridge is at what point do I get control back to my thread.
>
> Consider this:
>
> Producer thread -> Linked list with a QMutex Lock -> picked up by a consumer
> thread.
>
> My hacks have been, and I've seem many others do the same,
Where is the hack? (I mean which line).
> // a consumer thread may contain the following..
> while (running)
> {
> if (list.size())
> {
> anObject = list.front();
> // do some work
> list.pop_front();
> }
> sleep(1);
> }
>
> The docs and examples are such that I'm don't feel comfortable breaking away
> from this.
>
> If I just call exec and my run returns, how do I get any work done?
By putting it into run() and setting running to true before the while is
evaluated.
> Also, on this subject, can Trolltech build a true cross platform system object?
> QMutex is implemented using process objects and is not a true system wide
> lock. This is necessary when software is built as a collection of executables
> and not threads.
No idea, but QMutex is not supposed to be interprocess at all.
Andreas
--
[ signature omitted ]
Message 8 in thread
On Jun 6, 2007, at 10:54 AM, Andreas Pakulat wrote:
> On 06.06.07 10:18:14, Michael Simpson wrote:
>> Bradley,
>> I've done alot of thread programming. QT threads confuse me as
>> well and I
>> often feel like I am hacking the thread object to match my reality.
>>
>> In traditional thread programming, I pass an entry point to a
>> routine that I
>> want run. QThread has a pure virtual, "Run". I can write my run
>> and do some
>> looping that does some work. I never release control of that
>> loop. In the
>> examples, I see they set some things up and then call exec().
>> What I have
>> never been able to bridge is at what point do I get control back
>> to my thread.
>>
>> Consider this:
>>
>> Producer thread -> Linked list with a QMutex Lock -> picked up by
>> a consumer
>> thread.
>>
>> My hacks have been, and I've seem many others do the same,
>
> Where is the hack? (I mean which line).
The hack is that this is obviously not what Trolltech had in mind.
If I subvert the process, it will work fine on Windows because i know
Window's threading model. But what about other platform threading
models? I want to be certain that I use best practices so that my
code, when I choose to do it, will work the same way on other platforms.
>
>> Also, on this subject, can Trolltech build a true cross platform
>> system object?
>> QMutex is implemented using process objects and is not a true
>> system wide
>> lock. This is necessary when software is built as a collection of
>> executables
>> and not threads.
>
> No idea, but QMutex is not supposed to be interprocess at all.
On Windows, a "MUTEX" is a system object. I can lock the object in
one process and another process will wait until the lock is
releases. One property of a Windows mutex is that it is named. An
example of usage would be the Windows debugger. I can hook into it
by creating a mutex with a specific name and reading a shared memory
file. It is useful. Trolltech's QMutex is only valid within a
process on Windows.
For those have have a subscription to solutions, you will see that
Trolltech does not use the QMutex model in their shared memory code.
That the shared memory code is cross platform, this would lead me to
believe that a cross platform system mutex would be possible.
M
--
[ signature omitted ]
Message 9 in thread
On 06.06.07 15:23:28, Michael Simpson wrote:
> On Jun 6, 2007, at 10:54 AM, Andreas Pakulat wrote:
> >On 06.06.07 10:18:14, Michael Simpson wrote:
> >>I've done alot of thread programming. QT threads confuse me as well and I
> >>often feel like I am hacking the thread object to match my reality.
> >>
> >>In traditional thread programming, I pass an entry point to a routine that I
> >>want run. QThread has a pure virtual, "Run". I can write my run and do some
> >>looping that does some work. I never release control of that loop. In the
> >>examples, I see they set some things up and then call exec(). What I have
> >>never been able to bridge is at what point do I get control back to my
> >>thread.
> >>
> >>Consider this:
> >>
> >>Producer thread -> Linked list with a QMutex Lock -> picked up by a consumer
> >>thread.
> >>
> >>My hacks have been, and I've seem many others do the same,
> >
> >Where is the hack? (I mean which line).
>
> The hack is that this is obviously not what Trolltech had in mind. If I
> subvert the process, it will work fine on Windows because i know Window's
> threading model. But what about other platform threading models? I want to be
> certain that I use best practices so that my code, when I choose to do it, will
> work the same way on other platforms.
I guess I didn't really understand the problem... Well, I'm not a
threads guru but unless I'm totally off I think the QWaitCondition that
was suggested might be something to look at...
> >>Also, on this subject, can Trolltech build a true cross platform system
> >>object?
> >> QMutex is implemented using process objects and is not a true system wide
> >>lock. This is necessary when software is built as a collection of
> >>executables
> >>and not threads.
> >
> >No idea, but QMutex is not supposed to be interprocess at all.
>
> On Windows, a "MUTEX" is a system object. I can lock the object in one process
> and another process will wait until the lock is releases. One property of a
> Windows mutex is that it is named. An example of usage would be the Windows
> debugger. I can hook into it by creating a mutex with a specific name and
> reading a shared memory file. It is useful. Trolltech's QMutex is only valid
> within a process on Windows.
Not only on windows.
> For those have have a subscription to solutions, you will see that Trolltech
> does not use the QMutex model in their shared memory code. That the shared
> memory code is cross platform, this would lead me to believe that a cross
> platform system mutex would be possible.
Well, if there is a platform independent way the reason that Qt4 doesn't
provide this could simply be that not enough people requested this yet.
Andreas
--
[ signature omitted ]
Message 10 in thread
On Jun 6, 2007, at 1:18 PM, Michael Simpson wrote:
> If I just call exec and my run returns, how do I get any work done?
The whole point is that exec() does not return until *you* tell it
to. You use signals/slots to communicate with your thread's event
loop (running inside exec()). I've coded both event-driven threads
as well as more traditional pthreads-type QWaitCondition thread
loops, even in the same application, depending on the situation.
Brad
--
[ signature omitted ]
Message 11 in thread
On Wednesday 06 June 2007 19:18:14 Michael Simpson wrote:
> Bradley,
> I've done alot of thread programming. QT threads confuse me as well
> and I often feel like I am hacking the thread object to match my
> reality.
>
> In traditional thread programming, I pass an entry point to a routine
> that I want run. QThread has a pure virtual, "Run". I can write my
> run and do some looping that does some work. I never release control
> of that loop. In the examples, I see they set some things up and
> then call exec(). What I have never been able to bridge is at what
> point do I get control back to my thread.
>
> Consider this:
>
> Producer thread -> Linked list with a QMutex Lock -> picked up by a
> consumer thread.
>
> My hacks have been, and I've seem many others do the same,
>
> // a consumer thread may contain the following..
> while (running)
> {
[snip]
> }
>
> The docs and examples are such that I'm don't feel comfortable
> breaking away from this.
>
> If I just call exec and my run returns, how do I get any work done?
QThread::exec() is just like QApplication::exec(), it doesn't return until you
call QThread::quit() (or QThread::exit()). The idea is that you should be
able to accomplish the same thing with less work using an event driven
approach:
Producer::produce()
{
emit dataReady(data);
}
Consumer::consume(const Data &data)
{
// ...
}
The 'while (running)' and data queue is handling by Qt (QThread::exec() and
signal-slot marshalling). I've got a pretty simple example that might help as
well:
http://labs.trolltech.com/blogs/2006/12/04/threading-without-the-headache/
> Also, on this subject, can Trolltech build a true cross platform
> system object? QMutex is implemented using process objects and is
> not a true system wide lock. This is necessary when software is
> built as a collection of executables and not threads.
We're actually doing some work on that, and hope to have it done for 4.4 :)
--
[ signature omitted ]
Message 12 in thread
Cool, that really starts helping to clear things up...
:-)
I'm having a look at the video links also, thanks again.
Regards,
Nasser
On 6/6/07, Bradley T Hughes <bhughes@xxxxxxxxxxxxx> wrote:
> On Wednesday 06 June 2007 04:31:09 Nasser wrote:
> > Hello list,
> >
> > To some degree, my confusion comes when comparing my previous
> > understanding of Threads in general, with the model that is described
> > in Qt... I am reading books that describe threads and processes (such
> > as PThreads Programming, O'Reily ... and Operating System Concepts,
> > Wiley) and sometimes struggling to see consistency between those
> > models and what Qt describes.. However, I keep re-reading the Qt docs
> > and pick things up here and there, but sometimes I feel I am possibly
> > missing some important point.. so I would appreciate any feedback on
> > my analysis
> >
> > The Qt documentations say that objects "live" in a particular thread.
> > But I thought that all global data and heap memory are shared by all
> > threads.. I thought that threads essentially have access to all these
> > data objects.. so why do objects in Qt have this "ownership" concept?
>
> Remember, the documentation refers to QObjects only. Every QObject has
> affinity to a particular thread (this is what QObject::thread() returns).
> This affinity (or ownership) tells us 1) which thread the QObject was created
> in, 2) which thread we're going to use the QObject from, and 3) which thread
> delivers events to the QObject.
>
> We aren't changing the multi-threading model at all; the complete address
> space is visible and available to all threads, just like in the books you've
> been reading.
>
> There are a number of reasons why we do this:
> 1. To define how QObjects will receive events.
> 2. To allow signal-slot connections without explicit locking in the
> emitting/slot code.
> 3. To make it even more obvious that most QObject subclasses are not
> thread-safe (especially I/O classes, which are all essentially state
> machines).
>
> > And one important thing... when we talk about an object belonging to a
> > particular thread, are we talking about those objects living in the
> > heap, data segment, or in the thread's stack?... The whole idea of
> > object ownership makes sense if we are talking about the objects
> > created on the thread's stack.. but why can't different threads access
> > objects if they are on the heap? (assuming we correctly synchronise
> > access to them of course).. Because I thought that all threads in the
> > same process share the same heap and data segment - but they each have
> > their own stack.
>
> Thread affinity is not meant to convey any kind of ownership. The
> documentation seems to be a bit misleading, I'll see if I can correct that.
>
> > I do understand how threads can have their own event loop. Is it
> > because of this that we need the notion of ownership?
>
> This is why we need the notion of thread affinity, yes. Ownership is something
> else, and handled in other ways (by parents taking ownership of child or
> placing objects on the stack).
>
> > I have also been reading the article in the latest Linux Journal about
> > "Asynchronous Database Access with Qt 4.x".. It talks about this -
> > stating ownership, etc, but I still do not understand "why" it must be
> > respected.. I understood most of the article, except the part when it
> > talks about objects "living" in a thread... Just like the Qt docs..
>
> Think of it like a team or project inside of a larger department. Everyone in
> the department is associated with a team or project, and the team operates
> independenty from the other teams (mostly). It's this type of association
> that QObject::thread() mimics. Changing "teams" is something that often
> happens, and QObject can do it too (see QObject::moveToThread()).
>
> > Is this a Qt thing? I would appreciate some comments or if you
> > recommend some further reading that will help make this clearer, I
> > would greatly appreciate your time. For now, I will keep researching
> > this so as I clarify things.
> >
> > Also, when we talk about executing in the context of a particular
> > thread, what exactly does this mean? .. What makes the context of a
> > thread? I thought it's just the stack and registers (program counter,
> > stack pointer, etc)
>
> You almost answered your own question :)
>
> A thread context is the stack and register state, and saying "executing in the
> context of a particular thread" is the same as saying "executing in a
> particular thread."
>
> --
> Bradley T. Hughes - bhughes at trolltech.com
> Trolltech ASA - Sandakervn. 116, P.O. Box 4332 Nydalen, 0402 Oslo, Norway
>
--
[ signature omitted ]
Message 13 in thread
Ok, just spent some time playing around with some little programs I
made up and I think I have this more or less sussed out now.. I would
just appreciate some final thumbs-up if my understanding is correct:
> Remember, the documentation refers to QObjects only. Every QObject has
> affinity to a particular thread (this is what QObject::thread() returns).
> This affinity (or ownership) tells us 1) which thread the QObject was created
> in, 2) which thread we're going to use the QObject from, and 3) which thread
> delivers events to the QObject.
ok, the points above I was able to see them in action with my little
program, except the 2nd point - this is not necessarily strict is it?
Because if we have a QObject whose affinity is in a particular QThread
A, it does not mean that only QThread A will use that QObject, right?
.. however, if we do use that QObject from outside QThread A, then we
will need to make this threadsafe, since QThread A might be performing
some work on that QObject (via the event loop)
The first point - I finally understand this.. By "which thread created
the QObject", we really mean "which thread CREATED the QObject"... I
used to think that declaring the QObject inside the QThread was
enough, but actually it is not.. It is the moment we create an
instance of that QObject, that makes the difference.. also, if we made
the QObject in QThread A's construtor, then actually the affinity is
not with QThread A, but with the thread that called the QThread's
constructor.. (I saw this in a recent Qt mailing list topic)
> This is why we need the notion of thread affinity, yes. Ownership is something
> else, and handled in other ways (by parents taking ownership of child or
> placing objects on the stack).
ok, affinity is quite different from ownership.. Ownership basically
means "which object is responsible for deleting this object".. By
creating an object and passing in "this", we say that "this" will be
the parent of the new object... when "this" dies, then "this" will
also delete the new object... If we used stacks (rather than the heap
- ie allocated with "new" keyword), then this parent/child
relationship is implicit
And one other thing... I used
Qt::HANDLE tid = QThread::currentThreadId();
in order to see what thread is doing what.. If I have 2 QThreads, can
I compare them? .. I know that I can create my own QThread subclass
which have their own IDs, but this approach will not allow me to
compare the main thread with one of my subclasses (since the main
thread is not a subclass, therefore does not have an ID like my
subclasses).. anyway, its not a big deal - just might come in handy in
the future when I want to compare a Qthread subclass..
Enough from me - thanks a lot for clarifying things :-)
Regards,
Nasser
--
[ signature omitted ]
Message 14 in thread
On Thursday 07 June 2007 06:51:11 Nasser wrote:
> Ok, just spent some time playing around with some little programs I
> made up and I think I have this more or less sussed out now.. I would
>
> just appreciate some final thumbs-up if my understanding is correct:
> > Remember, the documentation refers to QObjects only. Every QObject has
> > affinity to a particular thread (this is what QObject::thread() returns).
> > This affinity (or ownership) tells us 1) which thread the QObject was
> > created in, 2) which thread we're going to use the QObject from, and 3)
> > which thread delivers events to the QObject.
>
> ok, the points above I was able to see them in action with my little
> program, except the 2nd point - this is not necessarily strict is it?
> Because if we have a QObject whose affinity is in a particular QThread
> A, it does not mean that only QThread A will use that QObject, right?
> .. however, if we do use that QObject from outside QThread A, then we
> will need to make this threadsafe, since QThread A might be performing
> some work on that QObject (via the event loop)
Right. The affinity is not a strictly enforced in anyway. If you want to
access the object from some other thread, you can do it, but you will have to
protected it (like you mentioned). Because of the affinity, you can be
guaranteed* that Qt will not access the object from a different thread (which
should make your life easier).
* Unless, of course, you're using Qt::DirectConnection between objects in
different threads.
> The first point - I finally understand this.. By "which thread created
> the QObject", we really mean "which thread CREATED the QObject"... I
> used to think that declaring the QObject inside the QThread was
> enough, but actually it is not.. It is the moment we create an
> instance of that QObject, that makes the difference.. also, if we made
> the QObject in QThread A's construtor, then actually the affinity is
> not with QThread A, but with the thread that called the QThread's
> constructor.. (I saw this in a recent Qt mailing list topic)
Exactly. Note also that QThread has affinity not to itself, but to the thread
that instantiated the QThread (usually the main() thread). This is one thing
that I know is confusing, and I'm trying to find ways of addressing it. I've
considered having start() change QThread's affinity to itself, and when the
thread exits it would move back, for example.
> > This is why we need the notion of thread affinity, yes. Ownership is
> > something else, and handled in other ways (by parents taking ownership of
> > child or placing objects on the stack).
>
> ok, affinity is quite different from ownership.. Ownership basically
> means "which object is responsible for deleting this object".. By
> creating an object and passing in "this", we say that "this" will be
> the parent of the new object... when "this" dies, then "this" will
> also delete the new object...
Right :)
> If we used stacks (rather than the heap - ie allocated with "new" keyword),
> then this parent/child relationship is implicit
Perhaps, but I would rather say using parent-child is unnecessary when putting
things on the stack.
> And one other thing... I used
> Qt::HANDLE tid = QThread::currentThreadId();
> in order to see what thread is doing what.. If I have 2 QThreads, can
> I compare them?
You can't compare QThread's directly, but you can compare pointers. There is a
1-to-1 relationship, 1 QThread always represents exactly 1 thread.
> .. I know that I can create my own QThread subclass
> which have their own IDs, but this approach will not allow me to
> compare the main thread with one of my subclasses (since the main
> thread is not a subclass, therefore does not have an ID like my
> subclasses).. anyway, its not a big deal - just might come in handy in
> the future when I want to compare a Qthread subclass..
Hint:
if (qApp->thread() != myObject->thread()) {
// ...
}
:)
--
[ signature omitted ]
Message 15 in thread
awesome, thank you for all the clarifications!
:-)
On 6/7/07, Bradley T Hughes <bhughes@xxxxxxxxxxxxx> wrote:
> On Thursday 07 June 2007 06:51:11 Nasser wrote:
> > Ok, just spent some time playing around with some little programs I
> > made up and I think I have this more or less sussed out now.. I would
> >
> > just appreciate some final thumbs-up if my understanding is correct:
> > > Remember, the documentation refers to QObjects only. Every QObject has
> > > affinity to a particular thread (this is what QObject::thread() returns).
> > > This affinity (or ownership) tells us 1) which thread the QObject was
> > > created in, 2) which thread we're going to use the QObject from, and 3)
> > > which thread delivers events to the QObject.
> >
> > ok, the points above I was able to see them in action with my little
> > program, except the 2nd point - this is not necessarily strict is it?
> > Because if we have a QObject whose affinity is in a particular QThread
> > A, it does not mean that only QThread A will use that QObject, right?
> > .. however, if we do use that QObject from outside QThread A, then we
> > will need to make this threadsafe, since QThread A might be performing
> > some work on that QObject (via the event loop)
>
> Right. The affinity is not a strictly enforced in anyway. If you want to
> access the object from some other thread, you can do it, but you will have to
> protected it (like you mentioned). Because of the affinity, you can be
> guaranteed* that Qt will not access the object from a different thread (which
> should make your life easier).
>
> * Unless, of course, you're using Qt::DirectConnection between objects in
> different threads.
>
> > The first point - I finally understand this.. By "which thread created
> > the QObject", we really mean "which thread CREATED the QObject"... I
> > used to think that declaring the QObject inside the QThread was
> > enough, but actually it is not.. It is the moment we create an
> > instance of that QObject, that makes the difference.. also, if we made
> > the QObject in QThread A's construtor, then actually the affinity is
> > not with QThread A, but with the thread that called the QThread's
> > constructor.. (I saw this in a recent Qt mailing list topic)
>
> Exactly. Note also that QThread has affinity not to itself, but to the thread
> that instantiated the QThread (usually the main() thread). This is one thing
> that I know is confusing, and I'm trying to find ways of addressing it. I've
> considered having start() change QThread's affinity to itself, and when the
> thread exits it would move back, for example.
>
> > > This is why we need the notion of thread affinity, yes. Ownership is
> > > something else, and handled in other ways (by parents taking ownership of
> > > child or placing objects on the stack).
> >
> > ok, affinity is quite different from ownership.. Ownership basically
> > means "which object is responsible for deleting this object".. By
> > creating an object and passing in "this", we say that "this" will be
> > the parent of the new object... when "this" dies, then "this" will
> > also delete the new object...
>
> Right :)
>
> > If we used stacks (rather than the heap - ie allocated with "new" keyword),
> > then this parent/child relationship is implicit
>
> Perhaps, but I would rather say using parent-child is unnecessary when putting
> things on the stack.
>
> > And one other thing... I used
> > Qt::HANDLE tid = QThread::currentThreadId();
> > in order to see what thread is doing what.. If I have 2 QThreads, can
> > I compare them?
>
> You can't compare QThread's directly, but you can compare pointers. There is a
> 1-to-1 relationship, 1 QThread always represents exactly 1 thread.
>
> > .. I know that I can create my own QThread subclass
> > which have their own IDs, but this approach will not allow me to
> > compare the main thread with one of my subclasses (since the main
> > thread is not a subclass, therefore does not have an ID like my
> > subclasses).. anyway, its not a big deal - just might come in handy in
> > the future when I want to compare a Qthread subclass..
>
> Hint:
>
> if (qApp->thread() != myObject->thread()) {
> // ...
> }
>
> :)
>
> --
> Bradley T. Hughes - bhughes at trolltech.com
> Trolltech ASA - Sandakervn. 116, P.O. Box 4332 Nydalen, 0402 Oslo, Norway
>
--
[ signature omitted ]