COM Aggregation   «Prev  Next»
Lesson 5 Reference counting
ObjectiveExamine reference counting issues under aggregation.

COM Reference Counting

Using the OuterCOMObj and InnerCOMObj objects from the last lesson, let's examine some issues related to reference counting in an aggregated object. We also need to extend our example to include COM servers. Assume that both OuterCOMObj and InnerCOMObj are implemented in in-process servers. OuterCOMObj is in OCOMSrv.dll, InnerCOMObj is in ICOMSrv.dll.

Reference counting in an aggregated object
Reference counting in an aggregated object

Reference Counting Mechanism

Recall that COM objects use a reference counting mechanism to track interface and object usage to support lifetime management of objects and servers. The following code fragment depicts a client using the aggregation of OuterCOMObj and InnerCOMObj (remember, the client is not aware of the aggregation).

COM Interface HRESULT
  1. Declares an HRESULT to use for COM return values
  2. Declares a pointer to interface IF2.
  3. The client creates an instance of OuterCOMObj asking for a pointer to IF2. The client thinks IF2 is implemented in OuterCOMObj, that is, the aggregated component is not visible to the client. As part of its start-up sequence, OuterCOMObj creates an instance of InnerCOMObj. A pointer to IF2 is returned to the client in pIF2
  4. Checks to return status of CoCreateInstance.
  5. Assumes we make a series of successful calls into interface IF2.
  6. Releases interface IF2.
Declares an HRESULT to use for COM return values.

reference Counting
In the code fragment above, the client correctly uses and releases a pointer to interface IF2. However, if we were to implement reference counting and server unloading as we did before (in COM Fundamentals I), we could have a problem. When the client calls IF2::Release, the call goes directly into InnerCOMObj, which decrements IF2's reference counter. COM will call DllCanUnloadNow in the inner COM server (ICOMSrv.dll) to see if the server can be unloaded. DllCanUnloadNow will see that all reference counters have a zero value and return S_OK, and COM will unload the server. Using these implementation techniques for reference counting means that none of this activity is visible to the outer COM object. When the inner COM server (ICOMSrv.dll) is unloaded, the inner COM object (InnerCOMObj) is removed from memory. We no longer have an aggregation of both objects, and OuterCOMObj thinks InnerCOMObj is still active.
This scenario illustrates another problem that must be solved when aggregating objects: How can aggregated COM objects work with the outer COM object to support lifetime management? Aggregation requires that all the COM objects involved must act like one object. All objects participating in the aggregation must support reference counting in such a way that all object lifetimes are synchronized. This means that all inner objects and the outer object are created and destroyed at the same time. We will answer this question and explain how interface navigation is supported in the next few lessons.