Page #70 (COM Context)

< BACK  NEXT >
[oR]

Object Context

We know very well by now that each object under COM+ has a context associated with it. This context maintains the run-time requirements for all the likeminded objects. An obvious question that arises is, is there a way for an object to avail its context information and perhaps change some run-time state?

Under COM+, each context in a process has a unique COM object that represents it. This object is called the object context (OC). Each OC is uniquely identified by a GUID, referred to as the context-ID.

Objects can access their context s OC by calling the CoGetObjectContext API. Following is its prototype:

 WINOLEAPI CoGetObjectContext(/*IN*/ REFIID riid, /*OUT*/ LPVOID * ppv); 

The first parameter to the API is the requested interface on the OC. The interfaces that are of interest to us are IID_IObjectContextInfo, IID_IObjectContextActivity, and IID_IObjectContextState. [2] The methods on these interfaces are explained in Tables 5.2, 5.3, and 5.4, respectively.

[2] There is yet another interface, IID_IObjectContext, that has been left for backward compatibility with Microsoft Transaction Server (MTS). However, the newer interfaces replace the functionality of this old interface.

Table 5.2. IObjectContextInfo Interface Methods

Method

Description

GetContextId

Returns the GUID that uniquely identifies the context to which the object belongs

GetActivityId

Returns the GUID that uniquely identifies the synchronization activity to which the object belongs

IsInTransaction

Indicates whether the object is or is not part of a transaction

GetTransaction

Returns the ITransaction interface of the transaction to which the object belongs

GetTransactionId

Returns the GUID that uniquely identifies the transaction to which the object belongs

Table 5.3. IObjectContextActivity Interface Methods

Method

Description

GetActivityId

Returns the GUID that uniquely identifies the synchronization activity to which the object belongs

Table 5.4. IObjectContextState Interface Methods

Method

Description

SetDeactivateOnReturn

Informs COM+ that it is okay to deactivate the object when the calling method returns. Meaningful if just-in-time activation (JIT) is enabled

GetDeactivateOnReturn

Returns a boolean value that indicates if the object is set to be deactivated on return. Meaningful if JIT is enabled

SetMyTransactionVote

Lets the object set its vote (as a boolean flag) when the object participates in a transaction

GetMyTransactionVote

Returns the current transaction vote setting

Activity-related methods are discussed in detail in Chapter 6 (Concurrency). Transaction-related methods are discussed in detail in Chapter 8 (Transactions). JIT-related methods are discussed in Chapter 11 (Scalability).

This leaves us with just one method to discuss, GetContextId. This method returns the GUID that identifies the context. The following code snippet shows how to use this method:

 STDMETHODIMP CMyTestA::DoIt()  {   CComPtr<IObjectContextInfo> spCI;    HRESULT hr = ::CoGetObjectContext(IID_IObjectContextInfo,      reinterpret_cast<void**>(&spCI));    _ASSERT (SUCCEEDED(hr));    GUID contextid;    hr = spCI->GetContextId(&contextid);    _ASSERT (SUCCEEDED(hr));    ...    return S_OK;  } 

Default Context

When one object activates another object, COM+ checks to see if the activator s context is compatible with the activatee s configuration and, if required, sets up proper interception services. Getting the context information is not a problem when the activator happens to be an object of a configured component. Each object has a context attached to it, that COM+ can retrieve. However, there are cases when the activator is either an object from a non-configured component or not an object at all (such as a stand-alone client program). The following code snippet shows a stand-alone program activating a configured component s object:

 int APIENTRY WinMain(HINSTANCE hInstance,             HINSTANCE hPrevInstance,             LPSTR   lpCmdLine,             int    nCmdShow)  {   ::CoInitialize(NULL);      // Initialize the COM system.    IMyTestBPtr sp;    HRESULT hr = sp.CreateInstance(__uuidof(MyTestB));    if (SUCCEEDED(hr)) {     sp->DoIt();    }    ...  } 

When CoCreateInstance is called on the MyTestB COM class, COM+ needs to match the context of the activator with the configuration of the class MyTestB. But what is the context of the activator in this case?

In order to facilitate context lookup, COM+ provides a notion of default context. A default context has the semantics of classic COM: it doesn t store any transaction, synchronization, or security-related attributes. As a matter of fact, the OC for the default context does not even support any of the context-related interfaces (try writing a small test program to get any of the context-related interfaces). The only reason this context exists is so that it can hold objects of a non-configured class.

Here is how it works:

Each executing program (process) consists of one primary thread (executing WinMain) and perhaps some worker threads. A thread indicates its interest in using COM by calling the API CoInitializeEx. Following is its prototype:

 WINOLEAPI CoInitializeEx(/*IN*/ LPVOID pvReserved,    /*IN*/ DWORD dwCoInit); 

The first parameter for this API is reserved for future use. The second parameter indicates the type of apartment the thread would like to enter into. Apartments are covered in the next chapter. An apartment type basically dictates how the threads dispatch the calls. There are two values for this parameter COINIT_APARTMENTTHREADED and COINIT_MULTITHREADED. This value is typically decided during development time.

graphics/01icon01.gif

The COM SDK requires you to define one of the following two macros before including <windows.h>. This makes the prototype for CoInitializeEx API available to the compiler.

 #define _WIN32_DCOM  #define _WIN32_WINNT 0x0500 


If the apartment type is fixed as COINIT_APARTMENTTHREADED, the developer can use a simplified variation of the API, CoInitialize. The following is its prototype.

 WINOLEAPI CoInitialize(/*IN*/ LPVOID pvReserved); 

CoInitialize(Ex) has to be called before most other COM APIs can be called (including CoCreateInstance). When CoInitialize(Ex) is called, COM+ initializes the COM library and attaches an appropriate default context to the thread (there is one default context for each apartment type). The only information that the context contains is the apartment type.

The thread continues to reside in the default context until the thread wishes to leave the context (and thereby terminating its use of any COM services) by calling another API, CoUninitialize. The following is its prototype:

 void CoUninitialize(); 

CoUninitialize should be called once for each successful call to CoIntializeEx or CoInitialize.

graphics/01icon01.gif

According to Microsoft documentation, if the parent thread has called CoInitialize(Ex), the child threads need not call the API. However, I have made it a practice to call CoInitialize(Ex) and CoUninitialize APIs, respectively, at the start and at the exit of any thread that I spawn.


So, when an object of MyTestB is being activated, COM+ first checks to see if MyTestB is a configured class. If it is a configured class, then, by definition, the default context will not match the configuration of the class. Hence, COM+ activates the object in a compatible context and returns a proxy pointer to the client.

If MyTestB is a non-configured class, COM+ checks to see if the threading model of the class is compatible with the default context (essentially the apartment type) of the activator. If it is, then COM+ activates the object in the default context of the activator. Otherwise, COM+ activates the object in the default context of a compatible apartment and returns a proxy pointer to the client.

In the above example, the activator was assumed to be a stand-alone program. A similar logic holds if the activator is an object of a configured class. The non-configured object being activated runs either in the activator s context, if the threading model is compatible, or in the default context of a compatible apartment.


< BACK  NEXT >


COM+ Programming. A Practical Guide Using Visual C++ and ATL
COM+ Programming. A Practical Guide Using Visual C++ and ATL
ISBN: 130886742
EAN: N/A
Year: 2000
Pages: 129

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net