Threading models confusion 
Author Message
 Threading models confusion

I'm trying to understand what happens in EXE servers when multiple
clients connect.  I'm quite prepared for someone to tell me that my
understanding is flawed!  The components will be built using the ATL
wizards from Visual Studio 6, and must be capable of operating on
Windows NT4.

For the case of 'Apartment threaded' CoClasses (where each CoClass has
'affinity' with a particular thread):
If multiple clients create CoClass instances on the server, are the
different instances in the same or different apartments?  Does it make
any difference if the instances are for different CoClasses?  If they
are accessed via the same apartment (i.e. the same thread) then I do not
need to serialise access to global data - if different apartments, I do.

For the case of free threaded CoClasses (operating in a MTA), the
objects have no thread affinity.  In this case the question is:
Will method invocations from different clients (via the local stubs)
access different CoClass instances from the same thread, or may a number
of calls be accessing different CoClass instances from a number of
threads at the 'same' time?

Is there any difference if the server is accessed from other hosts via
DCOM?

I could just run some tests, but I'd rather know what is supposed to
happen (not just what happens in one case).  TIA...



Mon, 28 Feb 2005 22:27:25 GMT  
 Threading models confusion

Quote:
> For the case of 'Apartment threaded' CoClasses (where each CoClass has
> 'affinity' with a particular thread):
> If multiple clients create CoClass instances on the server, are the
> different instances in the same or different apartments?  Does it make
> any difference if the instances are for different CoClasses?  If they
> are accessed via the same apartment (i.e. the same thread) then I do
not
> need to serialise access to global data - if different apartments, I

do.

This ultimately depends on how a class factory is coded. In the simplest
case, the main thread of the server enters STA and registers class
factories (with CoRegisterClassObject or, in ATL,
_Module.RegisterClassObjects) from that STA. A simple class factory then
creates object instance on whatever thread it is called from. In this
case, there is no multithreading - everything happens on the same STA
thread.

A server can deviate from this scenario in two ways. First, it can spin
several STA threads during initialization, and register different class
factories on different threads. Each class factory still creates
instances on the thread it is called from, so essentially you have one
STA per coclass (or you can combine several coclasses into a single
STA).

Second, a class factory itself may spin new STA threads when requested
to create an object, and create it on the new thread.
CComClassFactoryAutoThread is one such implementation. In cooperation
with CComAutoThreadModule, it maintains a pool of STA threads, and
reuses an existing thread or creates new one as necessary.

Of course it is possible to combine both approaches, though it is not
clear why anyone would want to do so.

But whatever the scenario, once an STA object is created on a particular
STA thread, it will always be called on the same thread. Access to
shared data may have to be protected though.

Quote:
> For the case of free threaded CoClasses (operating in a MTA), the
> objects have no thread affinity.  In this case the question is:
> Will method invocations from different clients (via the local stubs)
> access different CoClass instances from the same thread, or may a
number
> of calls be accessing different CoClass instances from a number of
> threads at the 'same' time?

The latter. Even simultaneous calls on the same object may execute
concurrently on different threads, let alone calls on different
instances or different coclasses.

Quote:
> Is there any difference if the server is accessed from other hosts via
> DCOM?

No.

--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Mon, 28 Feb 2005 23:13:39 GMT  
 Threading models confusion

Quote:
> I'm trying to understand what happens in EXE servers when multiple
> clients connect.  I'm quite prepared for someone to tell me that my
> understanding is flawed!  The components will be built using the ATL
> wizards from Visual Studio 6, and must be capable of operating on
> Windows NT4.

> For the case of 'Apartment threaded' CoClasses (where each CoClass has
> 'affinity' with a particular thread):

Your understanding is somewhat flawed, but not terribly (and not
surprisingly either...this isn't obvious unless you dig into it).  The
concept of "Apartment threaded" (or any of the other thread models) applies
only to in-process objects (i.e. DLLs).  Out of process objects behave by
whatever CoInitialize call the code indicates when you register them in the
start routines of the EXE itself.

I'm fairly sure that you could have some objects registered to different
apartment types in the same process, but this is purely a manual thing.
Marking the co-class has no effect on this.

FWIW, out of the box, all EXE servers are single threaded.  With a few
#defines, they become multithreaded.  If you want something fancier (like
thread pools), then you need to add a bit of code.

From the client perspective, by the way, he can't tell how your objects are
running at all, including even if two objects of the same CLSID exist in two
separate EXEs.

You may want to consider picking up a book like ATL Internals (Brent Rector
and Chris Sells) or perhaps Essential COM by Don Box if you really need to
delve into how this works or if you need to make it work a certain way.

HTH



Tue, 01 Mar 2005 06:03:20 GMT  
 Threading models confusion
First, thanks - this is very helpful.  Just a couple more questions (see
in line), if you don't mind...

Quote:

> "Graeme Cogger" wrote
> > For the case of 'Apartment threaded' CoClasses (where each CoClass has
> > 'affinity' with a particular thread):
> > If multiple clients create CoClass instances on the server, are the
> > different instances in the same or different apartments?

> This ultimately depends on how a class factory is coded. In the simplest
> case, the main thread of the server enters STA and registers class
> factories (with CoRegisterClassObject or, in ATL,
> _Module.RegisterClassObjects) from that STA. A simple class factory then
> creates object instance on whatever thread it is called from. In this
> case, there is no multithreading - everything happens on the same STA
> thread.

> A server can deviate from this scenario in two ways. First, it can spin
> several STA threads during initialization, and register different class
> factories on different threads. Each class factory still creates
> instances on the thread it is called from, so essentially you have one
> STA per coclass (or you can combine several coclasses into a single
> STA).

> Second, a class factory itself may spin new STA threads when requested
> to create an object, and create it on the new thread.
> CComClassFactoryAutoThread is one such implementation. In cooperation
> with CComAutoThreadModule, it maintains a pool of STA threads, and
> reuses an existing thread or creates new one as necessary.

OK, I understand that and MSDN shows how to use CComAutoThreadModule.
I guess that the class factories will still be created in a single STA
unless I manually code CExeModule::RegisterClassObjects()?

Quote:
> But whatever the scenario, once an STA object is created on a particular
> STA thread, it will always be called on the same thread. Access to
> shared data may have to be protected though.

> > For the case of free threaded CoClasses (operating in a MTA), the
> > objects have no thread affinity.  In this case the question is:
> > Will method invocations from different clients (via the local stubs)
> > access different CoClass instances from the same thread, or may a number
> > of calls be accessing different CoClass instances from a number of
> > threads at the 'same' time?

> The latter. Even simultaneous calls on the same object may execute
> concurrently on different threads, let alone calls on different
> instances or different coclasses.

What determines the threads the calls are made on?  (I guess I have to
code to allow for any thread and 'simultaneous' calls, but I'd like to
know what's happening).  I assume that it depends on how the IPC
mechanisms pass calls to the server's stub, but is there anything I can
do to get control over that?


Tue, 01 Mar 2005 17:22:46 GMT  
 Threading models confusion

Quote:
> > Second, a class factory itself may spin new STA threads when
requested
> > to create an object, and create it on the new thread.
> > CComClassFactoryAutoThread is one such implementation. In
cooperation
> > with CComAutoThreadModule, it maintains a pool of STA threads, and
> > reuses an existing thread or creates new one as necessary.

> OK, I understand that and MSDN shows how to use CComAutoThreadModule.
> I guess that the class factories will still be created in a single STA
> unless I manually code CExeModule::RegisterClassObjects()?

The class factory object itself is indeed created on the main STA. But
CComClassFactoryAutoThread::CreateInstance spins a new STA thread (or
reuses existing one from the pool), arranges for the new object to be
created on that thread, and returns a properly marshalled pointer. All
further calls to the newly created object are executed on the pool
thread, not on the main thread.

Quote:
> What determines the threads the calls are made on?  (I guess I have to
> code to allow for any thread and 'simultaneous' calls, but I'd like to
> know what's happening).  I assume that it depends on how the IPC
> mechanisms pass calls to the server's stub, but is there anything I
can
> do to get control over that?

RPC itself maintains a pool of MTA threads. It can create and terminate
them as needed. Your object is called from one of those threads. I
repeat - your object may be called from a thread you have not even
explicitly created. One consequence of this is that, if you link to CRT
statically, you should avoid certain CRT functions like strtok or
asktime. Those functions are stateful (use internal data that needs to
survive after the call returns), for which they use TLS. Normally, you
create a new thread with _beginthreadex and exit it with _endthreadex,
which take care of initializing and cleaning up CRT on a thread
appropriately

Now, when you are called by RPC pool thread, of course there are no TLS
structures for CRT configured on it. When you first call one of those
CRT functions that require TLS, it gets initialized. But when this
thread terminates, there is no _endthreadex to clean up, resulting in a
memory leak.
--
With best wishes,
    Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken



Tue, 01 Mar 2005 22:58:13 GMT  
 Threading models confusion
Thanks for all the help.  I always feel better about my designs when I
know what is going on under the skin!

Graeme



Fri, 04 Mar 2005 15:47:11 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. what threading model is default when no Threading model key

2. COM Threading Model for ISAPI Worker Threads

3. Exe server threading model - events from worker thread question

4. total confusion in single threaded exe server

5. Thread Confusion

6. Thread Confusion

7. Delgate and thread confusion

8. Threading Models

9. Changin Threading model causing serious problems

10. OLE/COM Viewer: Inproc Handler Tab Option->Threading Model (Question)

11. Threading models issues

12. question about the threading model

 

 
Powered by phpBB® Forum Software