IDirect3DDevice9 references (&)

Started by
4 comments, last by hplus0603 18 years, 1 month ago
Hello! Is it a good idea to use & references to a IDirect3DDevice9 ? What I'd like to do is to have (almost) all of my class constructors that need a IDirect3DDevice9 reference so that they are sure the device is okay :

class hello
{
private:
  IDirect3DDevice9 & m_Device;

public:
  hello(IDirect3DDevice9 & device) : m_Device(device) {}
};

function foo()
{
LPDIRECT3DDEVICE9 my_super_device;
// CreateDevice to my_super_device

hello my_hello(*my_super_device);
// use hello
}

Will that cause problems, because IDirect3DDevice9 is an interface? And is there some reason why this wouldn't be a good idea?
Advertisement
Every time you do:

LPDIRECT3DDEVICE9 dev2 = dev1;

you are supposed to increment the reference count. If dev2 is a reference then you
don't need to. I guess you can.

I would recommend using a com_ptr which handles the reference counting for sharing COM objects around. My com_ptr is below:

#ifndef	COM_PTR_H#define	COM_PTR_H#include <assert.h>template < typename T >class com_ptr{	typedef	T*		_pT;public:	//	copy constructor from an object pointer	com_ptr( T* other = 0) 		:		_p( 0 )	{		_p = other;		AddRef();	}		//	copy constructor from another com_ptr	com_ptr( const com_ptr< T >& other ) 		:		_p( 0 )	{		_p = other.Get();					AddRef();	}	~com_ptr() 	{		Release();	}	// assignment from T*	com_ptr< T >& operator=( T* rhs ) 	{		Release();				_p = rhs;		return *this;	}	// assignment from T* reference	com_ptr< T >& operator=( _pT& rhs ) 	{		Release();		_p = rhs.Get();		AddRef();		return *this;	}	// assignment from another com_ptr	com_ptr< T >& operator=( com_ptr< T >& rhs ) 	{		// Release this		Release();		_p = rhs.Get();		AddRef();		return *this;	}	// Dereferencing	T* operator->() 	{		return _p;	}		T&	 operator*()	{		return *_p;	}	T** operator&()	{		return &_p;	}	// Increment the reference count	void	AddRef() 	{		if ( _p )		{			_p->AddRef();		}	}	// Decrement the reference count	void	Release() 	{		if ( _p )		{			_p->Release();		}	}	// Reset	void	Reset() 	{		Release();		_p = NULL;	}	T* Get() const	{		return _p;	}	unsigned long		Ref()	{		if ( _p )		{			_p->AddRef();			return _p->Release();		}		return 0;	}private:	T*		_p;};#endif


Hope that helps,

Dave
I understand your idea of reference counting, if I'm not mistaking, it is used so that the object is deleted only when all references to it are deleted.

However, in my application, only the main app will Release() the device, all the other pointers are "read-only", in that situation, do I really need to have a reference count?
It's fine. Note that you might cause interesting crashes if the device is ever lost or needs to be recreated and you forget to refresh all your references... If you're careful, it'll work out fine, but it's not commonly done because references are immutable: if you need to recreate your device, you'd also need to recreate all of your objects that held references to the old device, losing any data they might have.

It gets messy quick, all because you didn't want a little pointer.

And, as Dave pointed out, you should use com_ptr or ATL's CComPtr wrappers.
Well it would be good practice to implement the COM pointer anyways. But for an application that is equally as simple as the first few D3D tutorials then there isn't alot of point. using com_ptr would be a bit more future-proof as well.

Dave
There are cases where you NEED to release and re-create the device -- just Reset() won't clear it. Thus, you should write your application so that it allows the device to be released and re-created. This means writing some little pattern in your system that receives notifications about the device changing, and doing the right thing in response.

When you store a reference to a COM object (texture, vertex buffer, device, effect, etc), you should ALWAYS store it in a CComPtr<> (from <atlbase.h>). If you store it anywhere else, you'll probably end up with resource leaks or bad release behavior.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement