Lesson 8 | In-process COM servers DllCanUnloadNow |
Objective | Describe what DllCanUnloadNow does. |
In-process COM servers DllCanUnloadNow
DllCanUnloadNow Description
Understanding DllCanUnloadNow
builds on the reference-counting concepts covered in the previous module and on the information on In-process servers as discussed earlier in this module.
Local/remote Transparency
COM's local/remote transparency isolates the location and activation of a server from the client. A client simply asks for a class factory and, using IClassFactory::CreateInstance
, creates instances of a COM object. Recall that COM uses reference counting to manage the lifetime of a COM object. When a COM object, via QueryInterface
, "gives away" an interface pointer (i.e., assigns the output pointer parameter to an interface), it increments a reference counter by calling AddRef
. The COM client calls Release
when it is finished using an interface pointer. Release
decrements the reference counter.
Reference counting
Reference counting supports lifetime management of the COM object. A COM server uses reference counts to track active (COM) objects.
A server can be unloaded from memory when all its reference counts are 0.
In-process servers provide function DllCanUnloadNow
to assist with the unloading process.
Periodically, COM will call into DllCanUnloadNow
to ask the server if it can be removed from memory.
In DllCanUnloadNow,
a server checks all its reference counts and server locks (i.e., set via IClassFactory::LockServer
).
How DllCanUnloadNow is implemented
Conceptually, implementing DllCanUnloadNow
is simple: Just check the global server-lock counter and each reference counter in each interface within each COM object. For convenience, many developers keep track of all outstanding objects using a global variable. Let us call this g_objcnt
.
Whenever a new object is created, g_objcnt
is incremented either in IClassFactory::CreateInstance
or in the constructor of the C++ class that implements the new COM object. Recall that in IUnknown::Release
, we check to see if the reference count goes to 0. If it is 0, we often delete the C++ class, effectively deleting the COM object.
We now decrement g_objcnt
either in Release
or in the destructor of the C++ class.
g_objcnt
acts as a counter for active COM objects. It is incremented in the context of IClassFactory::CreateInstance
when a new COM object is created, and it is decremented when the COM object is destroyed. DllCanUnloadNow
can now check g_objcnt
along with the server-lock count to determine if the server can be unloaded. Following is a typical implementation of
DllCanUnloadNow
.
//Global Reference Counters
ULONG g_server_locks = 0;
ULONG g_objcnt = 0;
STDAPI DllCanUnloadNow() {
if (g_server_locks == 0 && g_objcnt == 0)
return TRUE;
return FALSE;
}
If they are all 0, no COM objects within the server are in use. The server returns TRUE
. Upon seeing a non-zero return, COM will unload the in-process server. If any of the reference counts are non-zero or the lock counter is non-zero, the server returns FALSE
and COM leaves the server in memory.
dllCanUnloadNow - Exercise