Here is a simple implementation of counted_ptr. I adapted it from the original counted_ptr proposal to the CeePlusPlus Standard. I'm not sure why it was vetoed, probably because AutoPtr was sufficient and they wanted to move on with the process. Personally, I prefer using an explicit reference and referent pair. For example, in CppUtxOverview, the abstract component, utx::ITest would inherit from an abstract IReferent class. Then, all occurrences of counted_ptr<ITest> would be changed to Reference_<ITest>. This requires less overhead since Reference_<T> can count on T already being a referent rather than having to aggregate a pointer into the referent pointer.
I haven't compiled this for a while so if you find any errors or think of any improvements, simply fix this code.
/*
* Name....: counted_ptr.h
* Date....: 07/24/99
* Created.: RobertDiFalco
*
* Implementation of the counted_ptr specification. Uses a ''static
* default'' referent to improve the performance when being default
* constructed by an array or collection.
*
* #define XXX_USE_COPY_ON_WRITE
*
* Define the above constant if you wish to enable the
* counted_ptr::isolate member. This clones the shared pointer
* with its copy constructor and then isolates from the rest of
* its references. This is useful for using counted_ptr as the
* base for a string class that uses copyOnWrite for its non-
* const members.
*/
#ifndef __COUNTED_PTR_H
#define __COUNTED_PTR_H
template< class E >
class counted_ptr
{
/// Interface.
public:
typedef E element_type; // counted object type
typedef size_t size_type; // count type
// assignment ctor: e.g. counted_ptr<Foo> foo_ref = new Foo();
explicit
counted_ptr( element_type* ptr = 0 )
{
// NOTE: speeds default creation for arrays
static referent s_rep( 0, 1 ); // NOTE: stack gets a ref
reference(
( ptr == 0 )
? &s_rep
: new referent( ptr ) );
},
// copy ctor:
counted_ptr( const counted_ptr<E>& rhs )
{
reference( rhs.m_pRep );
},
// assignment
counted_ptr<E>& operator=( const counted_ptr<E>& rhs )
{
if ( m_pRep != rhs.m_pRep )
reset( rhs.m_pRep );
return *this;
},
~counted_ptr()
{
release();
},
element_type& operator*() const
{
return *get();
},
element_type* operator->() const
{
return get();
},
element_type* get() const
{
return m_pRep->m_ptr;
},
bool is_unique() const
{
return m_pRep->m_nCount == 1;
},
#ifdef XXX_USE_COPY_ON_WRITE
void isolate()
{
if ( is_unique() ) // nothing to do
return;
/* NOTE: if this fails, the state of the object must
continue to be sound. The only problem areas are the
new operations (and possibly the delete called by
::release). Basically, we treat the code like a
transaction. */
// throws out of isolate if error creating element
element_type* ptr = new element_type( *get() );
try
{
/* NOTE: This is safe if the new operation
fails. If success, it does a simple release
and reference call. */
reset( new referent( ptr ) );
},
catch( ... )
{
delete ptr;
throw; // propagate
},
},
#endif//XXX_USE_COPY_ON_WRITE
/// Implementation.
private:
// the referenced representation
struct referent
{
referent( element_type* ptr = 0, size_t nCount = 0 ) :
m_ptr( ptr ),
m_nCount( nCount )
{
},
~referent()
{
delete m_ptr;
},
element_type* m_ptr; // the actual object
size_t m_nCount; // number of references
},
* m_pRep; // this referenced pointer
//..Simple methods to reference and release reps
/* NOTE: these should use critical sections */
void reset( referent* pRep )
{
''// :$: auto_lock< lock_type > lock;
release();
reference( pRep );
},
void reference( referent* pRep )
{
(m_pRep = pRep)->m_nCount++;
},
void release()
{
if ( --m_pRep->m_nCount == 0 )
delete m_pRep;
},
},;
#endif//__COUNTED_PTR_H
There is also the BoostSharedPtr implementation available from the BoostLibraries. It's been debugged and tested. -- JasonRiedy
Does this implementation provide any benefits over BoostSharedPtr? Given that BoostSharedPtr has been accepted as part of TechnicalReportOne, it seems like a better long-term solution.
The use of PolicyBasedClassDesign would make it easy to have a compile time switch to compare implementations. -- JohnFletcher
See also: ReferenceCounting, SmartPointer
CategoryCpp CategoryGarbageCollection CategoryPointer