Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

bjmumblingmiles

Templated SafeRelease

This topic is 5540 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I saw this over at flipcode:
  
template <class T>
void SafeRelease(T& IUnk)
{
	if (IUnk)
	{
		IUnk->Release();
		IUnk = 0;
	}
}
  
and then followed a huge debate over it not really being type-safe, etc. they came up with lots of different ways to keep it from being used on a non com object, like this one:
  
template<typename T_>
void SafeReleaseCOM(const T_ *&iunknown_)
{
  IUnknown *pDummy = iunknown_;
  //...

}
  
My question is, why couldn''t you just pass a reference to an IUnknown pointer if you only want to use it on com objects? Am I missing something, or are the posters who came up with this stuff missing something? Brian J

Share this post


Link to post
Share on other sites
Advertisement
You missed the point: how could you prevent an unknowing coder from accidentally using the function on anything that implemented a Release() function?

You have to think beyond a little 1000 line piece of code written by one coder and think about millions of lines of code written by twenty coders.

Share this post


Link to post
Share on other sites
Exactly...so why couldnt you just pass an &*IUnknown to begin with instead of a template? Then it could only be used on COM objects...which is the point, right?


Brian J

Share this post


Link to post
Share on other sites
Yes, the original template leaves it open to any class which implements a Release method...


  
class DisplayManager {
public:
void Release() {
// this method releases resources so that

// other things can use them

}
void Reacquire() {
// this method reacquires the resources

}
};

DisplayManager* pDispManager = ....;


Now if some idiot does:


  
SafeRelease(pDispManager);
// do some stuff...

pDispManager->Reacquire();


Not only does this create a memory leak (you never delete the display manager) but you also get a seg fault if you use the nulled pointer afterwards when you call Reacquire()...

Regards,
Jeff

Share this post


Link to post
Share on other sites

  
void SafeRelease( IUnknown*& pUnk ) {
if( pUnk != NULL ) {
pUnk->Release();
pUnk = NULL;
}
}


OR, use the com smart pointer method (just something quick I whipped up to demonstrate)


  
struct IUnknown
{
virtual void AddRef() = 0;
virtual void Release() = 0;
};

template< typename IFace >
struct IsComInterface
{
IsComInterface() {
IFace* ptr = NULL;
IUnknown* pUnk = ptr;
}
};

template< typename IFace >
class SmartPtr
{
public:
SmartPtr() {

}
SmartPtr( IFace* p ) : mPtr( p ) {

}
~SmartPtr() {
if( mPtr != NULL ) {
mPtr->Release();
mPtr = NULL;
}
}

void operator=( IFace*& other ) {
if( mPtr != NULL ) {
mPtr->Release();
}
mPtr = other;
}

operator IFace*() { return mPtr; }

private:
IFace* mPtr;
IsComInterface< IFace > mAssert;
};


struct ITest : public IUnknown
{
ITest() {
AddRef();
}
void AddRef() {
++mRefCount;
}
void Release() {
--mRefCount;
if( mRefCount == 0 ) {
delete this;
}
}
private:
unsigned long mRefCount;
};

struct NotCOM
{
void AddRef() {}
void Release() {}
};

int main()
{
SmartPtr< ITest > sp1 = new ITest();
// This won''t compile

SmartPtr< NotCOM > sp2 = new NotCOM();
return 0;
}

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!