AddRef and Release

AddRef() function increments the reference count of the object. Release() function decrements the reference count of the object and when the life time expires or rather the reference count reaches zero, server deallocates the object.

addref and release

IUnknown and functions

IUnknown interface has three methods or functions. They are QueryInterface, AddRef and Release.

class IUnknown {
public:
  virtual HRESULT QueryInterface (REFIID riid, void **ppvObject) = 0;
  virtual ULONG   AddRef () = 0;
  virtual ULONG   Release () = 0;
};

IUnknown::AddRef

The IUnknown::AddRef method increments the reference count for an interface on an object. It should be called for every new copy of a pointer to an interface on a given object.

Prototype

ULONG AddRef(void);

Arguments

None

Return Value

Returns an integer from 1 to n, the value of the new reference count. This information is meant to be used for diagnostic/testing purposes only, because, in certain situations, the value may be unstable.

Remarks

Objects use a reference counting mechanism to ensure that the lifetime of the object includes the lifetime of references to it. Every COM object includes a 32 bit unsigned integer member variable for reference counting. Initial value of this reference count is zero. IUnknown::AddRef is called to stabilize a copy of an interface pointer and increments it by one. The updated value is returned. This is called by IUnknown::QueryInteface in server side and it can also be called when object is cloned as pointer. Reference count can have values from 1 to (2^31)-1. Reference count increment should be atomic in case of objects are handled in multi-threaded apartment.

IUnknown::Release

Decrements the reference count for the calling interface on a object. If the reference count on the object falls to 0, the object is freed from memory.

Prototype

ULONG Release(void);

Arguments

None

Return Value

Returns the resulting value of the reference count, which is used for diagnostic/testing purposes only. If you need to know that resources have been freed, use an interface with higher-level semantics.

Remarks

IUnknown::Release returns the current reference count and decrements the reference count of the object. Reference count decrement should be atomic if client is accessing multi-threaded apartment model. IUnknown::Release should be called by the client at the end when this object is no longer needed in the program. COM server deletes or frees the memory allocated by the object once this is called. Client should not call any interface function after this call.

Implement AddRef & Release

Declare the IDL interface file

/* IDL definition */
interface IMyCOMObj : IUnknown
{
  /* Additional functions */
};

Declare the C++ prototype header

class CMyCOMObj : public IMyCOMObj
{

public:
    CMyCOMObj();
    virtual ~CMyCOMObj();
    
    HRESULT __stdcall QueryInterface(
                                REFIID riid , 
                                void **ppObj);
    ULONG   __stdcall AddRef();
    ULONG   __stdcall Release();
 
    /* Additional functions */
 
    private:

    long m_nRefCount;   /* managing the reference count */
};
/* managing the all objects reference count */
extern long g_nComObjsInUse;

Implement AddRef and Release

ULONG CMyCOMObj::AddRef()
{
    InterlockedIncrement(m_nRefCount);
    return m_nRefCount;
}
ULONG CMyCOMObj::Release()
{
    ULONG ulRefCount = InterlockedDecrement(m_nRefCount);
    if (== m_nRefCount)
    {
        delete this;
    }
    return ulRefCount;
}

Call AddRef in QueryInterface

HRESULT CMyCOMObj::QueryInterface (REFIID   riid,
                                       LPVOID * ppvObj)
{
    /* Always set out parameter to NULL, validating it first. */
    if (!ppvObj) {
        return E_INVALIDARG;
    }
    *ppvObj = NULL;
    if (riid == IID_IUnknown || riid == IID_IMyCOMObj)
    {
        /* Increment the reference count and return the pointer. */
        *ppvObj = (LPVOID)this;
        AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

Reference counting all objects

We have used a counter named as g_nComObjsInUse to manage the count of live objects in the COM server. A COM server implements multiple objects. It often implements an IClassFactory class where objects are created with CreateInstance. So all class constructors should increment this global reference counter and all destructor should decrement it. DllCanUnloadNow() is called by the COM/DCOM framework when any client releases the objects and then terminates with CoUninitialize(). This g_nComObjsInUse counter will reach zero when all objects are deleted and this server is no longer needed. DllCanUnloadNow() should return S_OK or zero and this COM DLL will be unloaded from the memory.

CMyCOMObj::CMyCOMObj()
{
  InterlockedIncrement(g_nComObjsInUse);
}
CMyCOMObj::~CMyCOMObj()
{
  InterlockedDecrement(g_nComObjsInUse);
}
STDAPI DllCanUnloadNow()
{
  /* A DLL is no longer needed when it is not */
  /* managing any existing objects (i.e reference count is 0).*/
  /* We will examine the value of g_nComObjsInUse */
  
  if (g_nComObjsInUse == 0)
  {
    return S_OK;
  }
  else
  {
    return S_FALSE;
  }
 
}

About our authors: Team EQA

You have viewed 1 page out of 67. Your COM/DCOM learning is 0.00% complete. Login to check your learning progress.

#