Reference Counting

P

PeterAPIIT

Hello to all expect C++ programmer, recently i have developed a smart
pointer class but i don't know how to implement a reference counting.

My smart pointer is non-intrusive smart pointer.

My question is
1. I need a simple reference count ptr class
2. Does cyclic reference counting can be solved ?
3. Does policy based design is good approaches in smart pointer ?
4. What should i define in smart pointer template class ?
5. Does smart pointer syntax correct ?


In STL, there just write class U = XXX but why i need the template
<class>. What this mean ?

I know what is template.


This is my code so far.



Code:
template <typename T,
			template <class aType>
			class StoragePolicy = DefaultSPStorage,

			template <class >
			class OwnershipPolicy = RCPtr,

			template <class>
			class ConversionPolicy = DisallowConversion
		 >

class smart_ptr{};




#ifndef STORAGE_POLICY
#define STORAGE_POLICY


template <class aType>
class DefaultSPStorage
{
private:

	/*
		SmartPtr passes StoragePolicy<T>::T*
		to Ownership- Policy.
	*/
	aType * pImpl;

public:
	DefaultSPStorage () : pImpl(new aType())
	{
	}

	explicit DefaultSPStorage<aType>(aType* pointee) : pImpl(pointee)
	{
		if (!pointee) throw NullPointerException();
	}

	DefaultSPStorage<aType>& operator=(const DefaultSPStorage<aType>&
rhs)
	{
	}


	~DefaultSPStorage<aType>()
	{

	}


	aType* operator->()
	{
		if (pImpl != 0)
		{
			return pIpml;
		}
	}

	aType& operator*()
	{
		return *pImpl;
	}

	aType* GetImpl(const DefaultSPStorage & that)
	{
		return that.pImpl;
	}

	aType& GetImplRef(const DefaultSPStorage & that)
	{
		return that.pImpl;
	}

	/*	storageImpl.Destroy()

	*/
};



#endif






#ifndef RCPTR
#define RCPTR

template <class sameType>
class RCPtr
{

private:
	unsigned int* referenceCountPtr;

public:

	RCPtr<sameType>() : refereceCountPtr(new unsigned int(1))
	{
	}

	RCPtr<sameType>(const RCPtr & that)
	{
		unsigned int *temp = new unsigned int(1);

		temp = that.referenceCountPtr;
		referenceCountPtr = temp;
	}

	RCPtr<sameType>& operator=(const RCPtr<sameType>& rhs)
	{
	}

	~RCPtr<sameType>()
	{
		delete referenceCountPtr;
	}

	/*
		IncreaseRef
		DecreaseRef

		Realease

	*/




	/*	The Ownership policy must support
		intrusive as well as nonintrusive
		reference counting.

		Therefore, deallocation of memory is
		called by functionrather than
		implicitly destructor called because
		it can explicit called by user
	*/
};

#endif



My question is do you all have some instructions how to create the
reference counting ptr class.(What to do for non-intrusive smart
pointer).


hope you all can help.

A billion thanks for your help.
 
J

James Kanze

Hello to all expect C++ programmer, recently i have developed
a smart pointer class but i don't know how to implement a
reference counting.
My smart pointer is non-intrusive smart pointer.

Then why not just use boost::shared_ptr?
My question is
1. I need a simple reference count ptr class

Is that a question?
2. Does cyclic reference counting can be solved ?

It's possible, but it means extra analysis by the users. In
practice, reference counted pointers are best restricted to
known subsystems, where cycles are known not to occur.
3. Does policy based design is good approaches in smart pointer ?

It depends on how much you like unnecessary complexity.
4. What should i define in smart pointer template class ?

It depends on what you want the class to accomplish. (I've used
a number of different smart pointer classes in my career, for
different purposes.)
5. Does smart pointer syntax correct ?

I'm having trouble parsing that.
In STL, there just write class U = XXX but why i need the
template <class>.

Where do they just write class U = XXX?
What this mean ?

It depends on where it occurs. Try giving a complete example,
so we can figure out what you are talking about.
I know what is template.
This is my code so far.

It looks like a lot of excess complexity for no real purpose.
What is the class template supposed to do? Until you've defined
that, there's no point in writing a line of code. (I'm not
normally one of those "write the tests first" guys, but until
you've defined what the class is supposed to do enough so that
you could write the tests, there's no point in writing any
code.)
 
P

PeterAPIIT

Then why not just use boost::shared_ptr?


I want to learn how to write one because i'm a student.






Where do they just write class U = XXX?


It depends on where it occurs. Try giving a complete example,
so we can figure out what you are talking about.


What i mean is how to write template template arguments ?

I found that Loki wrote it like this
Code:
template <typename T,
			template <class aType>
			class StoragePolicy = DefaultSPStorage,

			template <class >
			class OwnershipPolicy = RCPtr,

			template <class>
			class ConversionPolicy = DisallowConversion
		 >

class smart_ptr{};


while STL did it another method which is

template<typename T, class u = XXX<S> >

Which one is better ?
 
K

Kai-Uwe Bux

I want to learn how to write one because i'm a student.

Then, just write a reference counted smart pointer and post the code. You
can be sure, it will receive criticism.

Moreover, start with a simple implementation. No bells, no whistles; i.e.,
no policies. It's around 100 lines. Just make it

template < typename T >
class refcounted_ptr {
// your code goes here
};


Where do they just write class U = XXX?


It depends on where it occurs. Try giving a complete example,
so we can figure out what you are talking about.


What i mean is how to write template template arguments ?

I found that Loki wrote it like this
Code:
template <typename T,
template <class aType>
class StoragePolicy = DefaultSPStorage,

template <class >
class OwnershipPolicy = RCPtr,


class smart_ptr{};


while STL did it another method which is

template<typename T, class u = XXX<S> >

Which one is better ?

These are difference template arguments:

template template arguments

and

template typename arguments

There is also template arguments that are just integer literals or pointers.
There is no _better_ since they serve different purposes.


Best

Kai-Uwe Bux
 
P

PeterAPIIT

These are difference template arguments:

template template arguments

and

template typename arguments

There is also template arguments that are just integer literals or pointers.


What is template template arguments and template typename arguments ?

The reason i write in policy based design is because this is the
requirement of the assignment.

My code so far:

Code:
#include "StoragePolicy.h"

template <typename T,
			template <class>
			class StoragePolicy = DefaultSPStorage,

			template <class>
			class OwnershipPolicy = RCPtr,

			template <class>
			class ConversionPolicy = DisallowConversion
		 >

class smart_ptr
{
	T* operator->()
	{
		return aType;
	}

	T& operator*()
	{
		return *aType;
	}
};



template <class aType>
class DefaultSPStorage
{
private:

	/*
		SmartPtr passes StoragePolicy<T>::T*
		to Ownership- Policy.
	*/
	aType * pImpl;

public:
	DefaultSPStorage () : pImpl(new aType())
	{
	}

	explicit DefaultSPStorage<aType>(aType* pointee)
	{
		if (!pointee)
		{
			throw NullPointerException();
		}
		else
		{
			pImpl = pointee;
		}
	}


	~DefaultSPStorage<aType>()
	{
		delete pImpl;
	}


	aType* operator->()
	{
		if (!pointee)
		{
			throw NullPointerException();
		}
		else
		{
			return pIpml;
		}
	}

	aType& operator*()
	{
		if (!pointee)
		{
			throw NullPointerException();
		}
		else
		{
			return *pImpl;
		}
	}

	aType* GetImpl(const DefaultSPStorage & that)
	{
		return that.pImpl;
	}

	aType& GetImplRef(const DefaultSPStorage & that)
	{
		return that.pImpl;
	}
};


template <class sameType>
class RCPtr
{

private:
	unsigned int* referenceCountPtr;

public:

	RCPtr<sameType>() : refereceCountPtr(new unsigned int(1))
	{
	}

	RCPtr<sameType>(const RCPtr & that)
	{
		unsigned int *temp = new unsigned int(1);

		temp = that.referenceCountPtr;
		referenceCountPtr = temp;
	}

	~RCPtr<sameType>()
	{
		delete referenceCountPtr;
	}


	void IncreaseRef()
	{
		*referenceCountPtr++;
	}

	void DecreaseRef()
	{
		*referenceCountPtr--;
	}

	/*
		IncreaseRef
		DecreaseRef

		Realease

	*/


	/*	The Ownership policy must support
		intrusive as well as nonintrusive
		reference counting.

		Therefore, deallocation of memory is
		called by function rather than
		implicitly destructor called because
		it can explicit called by user
	*/
};

int main(int argc, char *argv[])
{
/*	typedef smart_ptr<int,
		DefaultSPStorage, RCPtr> aSmtPtr;
*/
	smart_ptr<number, DefaultSPStorage, RCPtr> aSmtPtr;

	return 0;
}


I really need you all help.

Please help me.

A billion thanks in advance for your help.
 
K

Kai-Uwe Bux

What is template template arguments and template typename arguments ?

What about reading a little?

The reason i write in policy based design is because this is the
requirement of the assignment.

Ok.

My code so far:

Code:
#include "StoragePolicy.h"

template <typename T,
template <class>
class StoragePolicy = DefaultSPStorage,

template <class>
class OwnershipPolicy = RCPtr,

[QUOTE="template"]
[/QUOTE][/QUOTE]

Way too complicated. Start with a smart pointer that only has different
ownership policies, e.g., a reference counted ownership and a deep copy
policy.
[QUOTE]
class smart_ptr
{
T* operator->()
{
return aType;
}[/QUOTE]

Not good. The operator->() is a typical example of an operator that you will
want a policy to provide. There should be no hard-coded aType in your smart
pointer.
[QUOTE]
T& operator*()
{
return *aType;
}
};[/QUOTE]

operator* on the other hand, can be defined in terms of operator->() quite
generically as:

  reference  operator* ( void ) const {
    return( *( this->operator->() ) );
  }
  

Also: how is smart_ptr supposed to take advantage of all these policies?


[snip lots of "code"]

Maybe, you are in need of an example showing how policies actually can be
used to (a) reuse code that is common and (b) supply the code that differs.
Here is a simple smart pointer with two different ownership models:


#include <algorithm>
#include <functional>
using std::swap;


template < typename T >
class refcounted_policy {

  typedef T                    value_type;
  typedef value_type *         pointer;
  typedef value_type const *   const_pointer;

  struct count {
    pointer       the_ptr;
    unsigned long ref_count;

    count ( pointer ptr )
      : the_ptr ( ptr )
      , ref_count ( 1 )
    {}

    ~count ( void ) {
      delete ( the_ptr );
    }
    
  };

  count * count_ptr;

public:

  friend
  void swap ( refcounted_policy & lhs, refcounted_policy rhs ) {
    swap( lhs.count_ptr, rhs.count_ptr );
  }
  
  refcounted_policy ( pointer ptr )
    : count_ptr( new count ( ptr ) )
  {}
  
  refcounted_policy ( refcounted_policy const & other )
    : count_ptr ( other.count_ptr )
  {
    ++ count_ptr->ref_count;
  }

  ~refcounted_policy ( void ) {
    -- count_ptr->ref_count;
    if ( count_ptr->ref_count == 0 ) {
      delete( count_ptr );
    }
  }
  
  refcounted_policy & operator= ( refcounted_policy other ) {
    swap ( *this, other );
    return( *this );
  }

  const_pointer  operator-> ( void ) const {
    return( count_ptr->t_ptr );
  }
  
  pointer  operator-> ( void ) {
    return( count_ptr->t_ptr );
  }

};


template < typename T >
class deepcopy_policy {

  typedef T                    value_type;
  typedef value_type *         pointer;
  typedef value_type const *   const_pointer;

  pointer the_ptr;

public:

  friend
  void swap ( deepcopy_policy & lhs, deepcopy_policy rhs ) {
    swap( lhs.the_ptr, rhs.the_ptr );
  }
  
  deepcopy_policy ( pointer ptr )
    : the_ptr( ptr )
  {}
  
  deepcopy_policy ( deepcopy_policy const & other )
    : the_ptr ( other.the_ptr ? new value_type ( *other.the_ptr ) : 0 )
  {}

  ~deepcopy_policy ( void ) {
    delete ( the_ptr );
  }
  
  deepcopy_policy & operator= ( deepcopy_policy other ) {
    swap ( *this, other );
    return( *this );
  }

  const_pointer  operator-> ( void ) const {
    return( the_ptr );
  }
  
  pointer  operator-> ( void ) {
    return( the_ptr );
  }
  
};




template < typename T,
           template <class> class ownership_policy >
class smart_ptr :
  public ownership_policy< T >
{

  typedef ownership_policy< T > ownership;
  
public:

  typedef T                    value_type;
  typedef value_type *         pointer;
  typedef value_type const *   const_pointer;
  typedef value_type &         reference;
  typedef value_type const &   const_reference;

  smart_ptr ( pointer ptr = 0 )
    : ownership ( ptr )
  {}

  const_reference  operator* ( void ) const {
    return( *( this->operator->() ) );
  }
  
  reference  operator* ( void ) {
    return( *( this->operator->() ) );
  }

  friend
  bool operator== ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( lhs.operator->() == rhs.operator->() );
  }
  
  friend
  bool operator!= ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( lhs.operator->() != rhs.operator->() );
  }
  
  friend
  bool operator< ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( std::less<pointer>
             (  lhs.operator->(), rhs.operator->() ) );
  }

  friend
  bool operator<= ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( std::less_equal<pointer>
             (  lhs.operator->(), rhs.operator->() ) );
  }

  
  friend
  bool operator> ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( std::greater<pointer>
             (  lhs.operator->(), rhs.operator->() ) );
  }

  friend
  bool operator>= ( smart_ptr const & lhs, smart_ptr const & rhs ) {
    return ( std::greater_equal<pointer>
             (  lhs.operator->(), rhs.operator->() ) );
  }
    
};




#include <iostream>

struct Base {

  Base ( void ) {
    std::cout << "base is born.\n";
  }
  
  Base ( Base const & other ) {
    std::cout << "base is copied.\n";
  }
  
  virtual ~Base () {
    std::cout << "base dies.\n";
  }

  friend
  std::ostream & operator<< ( std::ostream & ostr,
                              Base const & obj ) {
    return( ostr << "base" );
  }
  
};


int main ( void ) {
  {
    smart_ptr< Base, deepcopy_policy > a_ptr ( new Base() );
    smart_ptr< Base, deepcopy_policy > b_ptr ( a_ptr );
    smart_ptr< Base, deepcopy_policy > c_ptr ( a_ptr );
    a_ptr = smart_ptr< Base, deepcopy_policy >();
    std::cout << "first handle deleted.\n";
    b_ptr = smart_ptr< Base, deepcopy_policy >();
    std::cout << "second handle deleted.\n";
  }
  std::cout << "------------------------\n";
  {
    smart_ptr< Base, refcounted_policy > a_ptr ( new Base() );
    smart_ptr< Base, refcounted_policy > b_ptr ( a_ptr );
    smart_ptr< Base, refcounted_policy > c_ptr ( a_ptr );
    a_ptr = smart_ptr< Base, refcounted_policy >();
    std::cout << "first handle deleted.\n";
    b_ptr = smart_ptr< Base, refcounted_policy >();
    std::cout << "second handle deleted.\n";
  }
}

Note that derived classes are not handled correctly (true cloning is missing
from the deepcopy policy). Also, there is no support for incomplete types.
In short, many things that you would expect from a good smart pointer are
missing.


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top