New to garbage collection & reference counting

Started by
3 comments, last by Aardvajk 15 years, 6 months ago
Hello, Recently I've been reading up on the concept of reference counting from various websites and books and I still don't quite get it. I was wondering if the code I have so far accurately uses the concept of reference counting:

class IRoot
{

	unsigned int _uiRefCount ;

   public :

	IRoot() : _uiRefCount(1) { }
	virtual ~IRoot() { }

	virtual unsigned int AddRefCount() { return ++_uiRefCount ; }

        virtual unsigned int Dispose() 
	{

	   unsigned int TempRefCount = --_u32RefCount ;

           if( TempRefCount == 0 )
	      delete this ;

	   return TempRefCount ;
	}
} ;

class MyTextureResource : public IRoot
{

     texture_info _info ;

   public :
 
     ~MyTextureResource()
     {
       // free internal resources
     }

     bool LoadFromFile( std::string file_name )
     {
       // populate '_info' with data from texture file
     }

     void Render() 
     {
        // renders texture
     }

} ;

int main( int argc, char** argv )
{

   MyTextureResource* res = new MyTextureResource() ;
   
   if( !res->LoadFromFile( "example.bmp" ) )
      cout << "Cannot load 'example.bmp'\n" ;

   res->Render() ;
   
   res->Dispose() ; // I'm done with it.

   cin.get() ;
   return 0 ; 
}

My reference counting system works fine for me but are there anything here that can be improved? Or, is there anything seriously flawed with the design? My other concern involves the function 'IRoot::AddRefCount'. Ideally (not in my code), when should this function be invoked? From my vague understanding of referencing counting, when two different objects point to the same piece of data then the reference count for that piece of data should be two. I'm not entirely certain how to translate that into code.
Advertisement
You could look at the source for boost::shared_ptr, which uses reference counting, for some general information, and some clues to your last question.
Quote:Original post by Yeshua666
My reference counting system works fine for me but are there anything here that can be improved? Or, is there anything seriously flawed with the design?


You do manual reference counting. AddRefCount can be used to share the object between objects with different life-times. An automatic reference counting system like the proposed boost shared pointer is a much stronger mechanism (although the syntax is not very cool).
This is similar to the reference counting that I use in my project. I also added another feature which has been invaluable to me when debugging my project. I created a IRootManager class which keeps track of every IRoot object that has been created. Whenever an IRoot object is created, it calls the manager and adds itself to a list. Whenever one is about to be destroyed, it removes itself from the list. This has been very helpful tracking down memory leaks and other problems. I can look at any time and see exactly how many of each object exists. If you wanted to go one step farther, you could record which objects still hold references to other objects.

Of course, all of this extra stuff you will want to disable in final builds, so I would recommend using the preprocessor to do that.
scottrick49
Quote:Original post by Yeshua666
From my vague understanding of referencing counting, when two different objects point to the same piece of data then the reference count for that piece of data should be two. I'm not entirely certain how to translate that into code.


This was an old attempt I made at a reference-counting pointer. It's probably buggy as hell and will cause your PC to explode, but I bravely post this then hide under the table before the onslaught starts.

In other words, please don't use this but it might give you more of an idea how you can get reference-counted pointers to the same underlying object working without having to wade through the source for boost::shared_ptr.

#ifndef refptr_H#define refptr_Htemplate<class T> class ref_ptr{private:class internal_rep{public:	internal_rep(T *p) : p(p),refs(1) { }	~internal_rep(){ delete p; }	T *p; int refs;};	internal_rep *i;public:	ref_ptr(T *p=0);	ref_ptr(const ref_ptr &r) : i(r.i) { ++i->refs; }	~ref_ptr(){ if(--i->refs==0) delete i; }		ref_ptr &operator=(const ref_ptr &r){ if(&r!=this){ if(--i->refs==0) delete i; i=r.i; ++i->refs; } return *this; }	ref_ptr &operator=(T *p);		T *operator->(){ return i->p; }	T &operator*(){ return *(i->p); }	const T *operator->() const { return i->p; }	const T &operator*() const { return *(i->p); }};template<class T> ref_ptr<T>::ref_ptr(T *p) : i(0){	try		{		i=new internal_rep(p);		}			catch(...)		{		delete p; throw;		}}template<class T> ref_ptr<T> &ref_ptr<T>::operator=(T *p){	internal_rep *temp=0;	try		{		temp=new internal_rep(p);		}	catch(...)		{		delete temp;		throw;		}	if(--i->refs==0) delete i; i=temp; return *this;}#endif


Now, everyone else wade in and give me a kicking... [smile]

This topic is closed to new replies.

Advertisement