Technical Notes
Previous |
Home
Threading Models and Apartments
- An apartment is the execution context of the object. A thread also represents the execution context.
- From the point of view of threading, an object could be,
- Thread-aware
- Thread-oblivious
- Obviously an object that is oblivious to threading issues must be somehow protected from concurrent access. This protection is provided by COM through Apartments.
- Any COM library call can be made only by a thread that is already a part of an apartment. A thread does this by calling
CoInitializeEx
(CoInitialize
simply calls CoInitializeEx
internally). The second parameter to this function determines the apartment type.
- An apartment could be single-threaded (STA) or multi-threaded (MTA).
- Regardless of the apartment type, objects within the same apartment have direct access to each other (even if they live on different threads as the case could be in MTA's).
- However, inter-apartment access requires marshalling.
- An apartment is not just a conceptual entity; it has real physical consequences.
- When a thread specifies that it belongs to an STA, that thread (being the only thread) must have a message queue.
- The COM library serializes all calls to the server through this queue. When the server is handling a message the message loop, obviously, is not active, causing the Operating System (OS) to put subsequent messages in the message queue.
- What this effectively means is that regardless of the number of clients there are for a single object in the server or the number of objects in the server (and their clients) only one request can be serviced at a given point of time.
- Here a question may arise as to who handles the messages that are posted to the STA through the message queue? The answer is - the COM library does. When the server calls
DispatchMessage
(see discussion on the DispatchMessage
API call here) the message is dispatched to a callback implemented by the COM library. Processing these messages are one of the "real physical consequences" we talked about earlier.
- You cannot call
DispatchMessage
unless a WNDCLASS
has been registered on that thread (note that message queues are specific to threads and not processes) and a window has been created using that class. However in case of outprocess servers we can do so (i.e., call DispatchMessage
without a window). This is possible because a WNDCLASS
is registered and a window created when the server calls CoInitialize
. CoInitialize
creates a hidden window to which the messages are posted.
Inter-apartment Marshalling
- Let us consider the first scenario. Both the client and the server are of a compatible apartment type. Therefore if the client creates an STA, the server can simply join this apartment. No marshalling is required.
- But in the second and the third scenarios, COM would create a separate apartment for the server. According to the COM specifications interface pointers must now be marshalled between these two apartments.
- The question may now arise as to the need for such marshalling as the server is in the same address space as the client. The need for such marshalling is immediately evident when the need for apartments are considered.
- In case the client creates more than a single thread (which means more than a single apartment) and wishes to access an interface pointer from those threads it must be marshalled. This is so because if the server is an STA (and therefore not thread-aware) concurrent access by the client may break the server. There is no way for COM to provide the protection that it provides through STA's if the interface pointers will be directly accessed.
- Secondly, if the server is an MTA and the client an STA, if there are outgoing interfaces on the server that the client implements, direct access to this implementation by the server (from multiple threads) may break the client.
- Therefore it is always a good idea to marshal interface pointers among STA's even when they belong to the same process (note that this implicates the provision of marshalling code even with inproc servers).
Previous |
Home