views:

52

answers:

4

all the D3D interfaces are derived from COM's IUnknown interface, so I though I'd take an easy route for releasing D3D objects and use something like this:

__inline BOOL SafeRelease(IUnknown*& pUnknown)
{
    if(pUnknown != NULL && FAILED(pUnknown->Release()))
        return FALSE;

    pUnknown = NULL;
    return TRUE;
}

this doesn't work though, as the compiler will generate invalid type conversion error(s), when I try to use it. the only way around it I could think of was this:

__inline BOOL SafeRelease(void* pObject)
{
    IUnknown* pUnknown = static_cast<IUnknown*>pObject;
    if(pUnknown != NULL && FAILED(pUnknown->Release()))
        return FALSE;

    return TRUE;
} 

but then I loose some functionality and it also looks(and is) very dodgy. is there a better way to do this? something that works like my first example would be optimal, though I would like to avoid using any macros(if its possible)

+1  A: 

A template function solves your problem:

template<class T>
__inline bool SafeRelease(T*& pUnknown)
{
    if (pUnknown == NULL) return false;
    if (0 == pUnknown->Release()) 
        pUnknown = NULL;
    return true;
}
Hans Passant
thanks, works great! totally forgot about the 'auto-typing' done by the templater
Necrolis
The code in the question and in this response is incorrect. IUnknown::Release() returns a ULONG, not an HRESULT. The ULONG is usually the refcount of the object. It is not an indicator of whether the Release() succeeded or failed.See IUnknown::Release() documentation at http://msdn.microsoft.com/en-us/library/ms682317(VS.85).aspx
Ants
Oh Lord, downvote the question.
Hans Passant
@ants: I was just going along with the comments in WinError.h:`// The return value of COM functions and methods is an HRESULT.`guess then thats fixed up then as well, thanks for pointing it out :)
Necrolis
A: 

If you could do what you originally wrote, then you would violate type safety:

IDirect3DDevice *blah;
IUnknown *bar;
IUnknown *&unknown= blah;
unknown= bar;

Clearly, assigning bar to unknown would mean that blah points to an IUnknown, which would violate type safety.

nobugz's solution is probably what you want to do, although I would argue that setting those pointers to NULL doesn't increase the quality of your code. If you need to ensure that other code won't Release multiple times, you probably should go fix that code rather than making buggy code not fail.

MSN
I see where it would cause a problem, but I was getting problems even up casting a IDirect3DDevice* to an IUnknown*, which should work
Necrolis
MSN
A: 

I haven't worked with DirectX in a while but I remember it has a SAFE_RELEASE macro somewhere in it's headers. Google code search shows it's in dxutil.h.

Idan K
I wanted to avoid using macros for a few reasons, one being that I can't check is the release succeeds, though when I googled "SafeRelease D3D COM" I got nothing of use
Necrolis
+3  A: 

The commonly taken route for dealing with COM resources is to employ RAII and let helper classes like ATLs CComPtr or CComQIPtr handle reference counting for you as far as possible.

void f() {
    CComPtr<IDirect3DDevice> sp3dDev;
    getDevice(&sp3dDev);
    // ... do stuff
} // smart pointer gets destroyed, calls Release() if valid
Georg Fritzsche