|
Proxy Object Code
Submitted by |
Proxy objects are extremely useful classes that prevent resource leaks. They
also simplify code and can provide portability benefits. A recent Code Of the
Day example was excellent other than the fact that it had a global locked memory
leak. This is especially bad because locked memory can not be swapped out by
window's virtual memory manager. To solve this type of problem, I wrote the
simple class below.
The basic idea behind Proxy objects is that they perform the resource grab in
the constructor, if possible, and they free the resource in the destructor.
Proxy objects are created on the stack as temporary variables. That way one
doesn't have to remember to free them explicitly. When the Proxy goes out of
scope, the resouce is automatically freed.
Proxy objects are useful for ensuring proper cleanup of any precious resource,
such as memory, gdi handles, threads, etc.
In addition, they are very useful in graphics - I use proxy objects to set
temporary D3D renderstates. When they go out of scope, it puts the renderstate
back how it was before. This really cleans up rendering code.
Another advantage of proxy objects is that they provide a nice way to hide O/S
specific behavior. You could swap out different Proxy object classes for
different operating systems without effecting the game code itself.
|
Download Associated File: proxyobject.txt (1,489 bytes)
/*
COTD - Proxy Object Code - by D. Sim Dietrich Jr. [simmer@pacbell.net]
Here is an example to handle creating and freeing locked down memory in Win32 :
*/
class GlobalAllocProxy()
{
private HGLOBAL hMem;
private bool bLocked;
public GlobalAllocProxy( const int& size )
{
hMem = GlobalAlloc( size );
};
public void* Lock()
{
void* pMem = 0;
if ( !mbLocked && ( hMem != 0 ) )
{
pMem = GlobalLock( hMem );
mbLocked = ( pMem != 0 );
}
return pMem;
}
public void Unlock()
{
if ( mbLocked )
{
GlobalUnlock( hMem );
mbLocked = false;
}
}
public ~GlobalAllocProxy()
{
if ( hMem )
{
UnLock();
GlobalFree( hMem );
}
}
}; // Class GlobalAllocProxy
Here is an example that shows how to use an abstract base class to support portability for CriticalSections. You could use a typedef or #define to make the type created completely hidden from the main code.
// The following code piece was contributed by Bobris:
class Mutex
{
public:
Mutex() { InitializeCriticalSection(&mCS); }
~Mutex() { DeleteCriticalSection(&mCS); }
void enter() { EnterCriticalSection(&mCS); }
void leave() { LeaveCriticalSection(&mCS); }
private:
CRITICAL_SECTION mCS;
};
class Lock
{
public:
Lock(Mutex &aMutex): mMutex(aMutex) { aMutex.enter(); }
~Lock() { mMutex.leave(); }
private:
Mutex &mMutex;
};
|
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|