|
COM Apartments Author: Richard Grimes Win32 is multi threaded, that means that there is the illusion that there is more than one thread of execution running at one time. I say illusion because unless you have a machine with more than one processor and an operating system that supports more than one processor (like NT, but not Windows 98) then the operating system will simulate a mult threaded environment by running pieces of code using a thread scheduler. This software essentially splits up the CPU's time between the threads of execution, the scheduler decides which thread should run and it determines how long the thread should run. When a thread has had its allotted time it is 'suspended' which means that the scheduler decides that another piece of code should run. Although you do have a little control over how this process works, the basic mechanism is that you present a piece of code to the operating system, and the OS decides when that code is run. It is quite a brutal environment to run in, because your code does not necessarily know if it will complete its task before some other code running on the same machine will complete what it is doing. COM has had to satisfy many requirements on Win32. For a start, when it appeared there was some code that had come from Win16 where there was only ever one thread of execution (and if that code decided to keep the CPU, there was nothing any other code could do). In addition, COM had two main goals: it was the basis of controls which usually had a user interface (and hence had windows), and COM was used to connect together code in different processes and potentially on different machines, such code had no UI but had a requirement to have a good performance. Microsoft came up with the idea of 'apartments', this may make sense to the American ear, but the conversion to UK English ('flats') is confusing and sounds a bit comical, so let's not dwell on that. Essentially an apartment groups together components of a similar concurrency requirement. If two components run in the same apartment it means that they have the same requirements about which and how many threads can access them. Win95, Win98 and NT4 define two types of apartments, the Single Thread Apartment (STA) and the Multi Threaded Apartment (MTA). An STA means that only one thread will access code in the apartment. Thus any component in that apartment can be assured that the _same_ thread will access its code. In addition, if there is more than one component in the apartment it means that only one component in the apartment will have an active call at any one time - MTS uses this property of STA's to maintain transaction isolation, but I will leave that for another discussion. Of course, there may be many clients trying to access code in an STA, so there must be some mechanism to make sure that a request to run a method on a component is only performed by the single thread that runs in the STA. This is done by COM insisting that all requests to run STA code is actually posted as a windows message to a message queue - STA synchronization is merely the STA thread using a GetMessage/DispatchMessage pump. This is fortuitous because if a message comes into the pump that is bound for a UI window it means that COM will help that message on its way. If an apartment thread does not do this (for example an MTA thread, which I'll come to in a minute) then it will mean that UI messages will not be dispatched, so they will not be handled and hence the UI will freeze - not a particularly good feature. The rule is simple, if a component has a UI then it must be an STA component (and if it is an inproc component, it must have a ThreadingModel of Apartment). Further, if a server is used to run STA components and that server creates threads, those threads _must_ have a GetMessage/DispatchMessage message pump. Some components do not have a UI, which means that they do not need to pump a message queue. Those components are good candidates to be run in the MTA. A process only ever has one MTA (it can have more than one STA) and this means that _every_ thread in the MTA has unfettered access to _any_ code in the MTA. There can be any number of threads in the MTA, you may create threads to run in it, and COM may create threads in it too. This means that any code that runs in the MTA must be designed to allow ulti threaded access. If the component has code that should only be accessed by one thread at a timethen that code should be protected to ensure that only one thread has access. Much code is sensitive like this, for example any code that accesses global, static, or class members. In these cases you should use a critical section, or a mutex to prevent more than one thread accessing the code concurrently. This is a good thing because it means that you target your synchronization code to just a small part of a method, as opposed to an STA where an entire method is run by a single thread. However, MTA component cannot have a UI because it cannot be made to pump a message queue regularly. An inproc component that is designed to run in the MTA should have a ThreadingModel of Both or Free. If Both is used it means that if the code that creates the component is in an STA, then the component will be created in the STA, if the calling code is in the MTA then it will be created there. Here are some recommendations:
Mail a question to the author!! As part of the IDevResource commitment to Open Publishing, all of our authors are available to answer all of your trickiest questions at Author Central. For information about the authors, or to mail a question, visit them at Author Central. Did you like this article? If you liked this article, tell us about it. You can email your remarks to us at [email protected] Have your say about the article. You can make your point about the article by mailing [email protected] (If you haven't allready joined, you can join by going to onelist.com/community/dev-com). Want to read more articles by this author? Try these: Byte size articles: ATL Server By Richard Grimes, 220200 COM and Apartments By Richard Grimes, January 7th 2000 An Introduction to WTL By Richard Grimes, January 7th 2000 An Introduction to Interface Programming By Richard Grimes, January 7th 2000 Full size articles: What is Async COM? By Richard Grimes. Microsoft Transaction Server By Richard Grimes, December 9th 1999 What COM is all about By Richard Grimes, December 6th 1999 Further Reading:
More ByteSize articles: 'ILoveYou' By Richard Grimes, 200500 COM+ 2.0 - First Announcement of Microsoft's New Technology By Richard Grimes, 100500 How to use DDX with WTL? By Girish Bharadwaj, 270300 ATL Server By Richard Grimes, 220200 COM Threading Models By Gopalan Suresh Raj, 070200 ActiveX & COM By Gopalan Suresh Raj, 270100 Type Library Info, XML and a bit of XSL for fun! by Richard Anderson 121199 COM and Apartments By Richard Grimes, 070100 What is WTL? By Richard Grimes, 070100 An Introduction to Interface Programming By Richard Grimes, 070100 Some links on COM:
Author Bio: Author: Richard Grimes Richard Grimes started programming aeons ago on 8-bit computers and hasn't looked back since. He has spent an interesting time as a research scientist (the little known "Grimes Effect" is his creation), underpaid time as a computer trainer and done time as a distributed object developer. ATL took hold of Richard while he was part of a team developing a COM-based workflow system and its elegance and simplicity has had a lasting effect on him. Although his is not an obsessively pure COM existence, he finds that an ATL-assisted COM lifestyle gives him more time to enjoy his garden. Go to Richards pages in Author Central. Contribute to IDR: To contribute an article to IDR, a click here.
|
|