PIRL  PIRL++

Public Member Functions | Protected Member Functions

PIRL::Reference_Counted_Pointer< T > Class Template Reference

A Reference_Counted_Pointer acts like a normal pointer with the addition of reference counting. More...

#include <Reference_Counted_Pointer.hh>

List of all members.

Public Member Functions

 Reference_Counted_Pointer (T *pointer=0)
 Construct a Reference_Counted_Pointer for a normal pointer.
 Reference_Counted_Pointer (const Reference_Counted_Pointer< T > &RCP)
 Copy a Reference_Counted_Pointer.
 ~Reference_Counted_Pointer ()
 Destroy this Reference_Counted_Pointer.
Reference_Counted_Pointer< T > & operator= (const Reference_Counted_Pointer< T > &RCP)
 Assign another Reference_Counted_Pointer to this Reference_Counted_Pointer.
Reference_Counted_Pointer< T > & operator= (T *pointer)
 Assign a pointer to this Reference_Counted_Pointer.
T & operator* () const
 Dereference this Reference_Counted_Pointer.
T * operator-> () const
 Access the pointer value of this Reference_Counted_Pointer.
 operator T * () const
 Get the value of the pointer held by this Reference_Counted_Pointer.
 operator bool () const
 Test if this Reference_Counted_Pointer has a pointer with a non-NULL value.
bool operator== (const Reference_Counted_Pointer &RCP) const
 Test if this Reference_Counted_Pointer is equivalent to another.
bool operator!= (const Reference_Counted_Pointer &RCP) const
 Test if this Reference_Counted_Pointer does not equal another.
bool is_distinct_from (const Reference_Counted_Pointer &RCP) const
 Test if this Reference_Counted_Pointer is distinct from another Reference_Counted_Pointer.
long reference_count () const
 Get the reference count.

Protected Member Functions

void dispose ()
 Dispose of the Reference_Counted_Pointer contents if no longer in use.

Detailed Description

template<class T>
class PIRL::Reference_Counted_Pointer< T >

A Reference_Counted_Pointer acts like a normal pointer with the addition of reference counting.

A Reference_Counted_Pointer associates a reference counter, allocated on the heap, with a copy of a normal pointer. The normal pointer may refer to any type of object other than an array, but the object must have been allocated on the heap (i.e. with the new method).

Whenever a Reference_Counted_Pointer is copied, or assigned to another Reference_Counted_Pointer, both the pointer to the referenced object and the pointer to its reference counter are copied and the resulting shared reference count is incremented. Whenever a Reference_Counted_Pointer is destroyed, or assigned a Reference_Counted_Pointer or normal pointer that refers to a object different from the one currently being referenced, its reference count value is decremented and if the value becomes zero both the referenced object and the reference counter are deleted; otherwise both remain valid for any other Reference_Counted_Pointers using them. In this way a Reference_Counted_Pointer may be deleted as usual but if there are any other references to the shared object being referenced it will only be deleted when the last reference is deleted.

A Reference_Counted_Pointer may be dereferenced, but it may not be altered (e.g. incremented or decremented).

When sharing a normal pointer the issue of object ownership needs to be considered: Only the owner of the object is to delete it (it can only be deleted once). This creates a problem when the object is to be shared by multiple objects that will use the reference object: There can be only one owner so who deletes the object can be difficult to determine. The Reference_Counted_Pointer solves this problem by transferring ownership of the referenced object to a lightweight object that acts like a normal pointer to the object but keeps track of the number of shared references to the object, automatically deleting the object when there are no more external references to it. This "last one to leave turns out the lights" paradigm enables the object to be shared by many objects with no concern for ownership. In particular, a Reference_Counted_Pointer may be a data member of an object while the Reference_Counted_Pointer is copied to other objects and the referenced object will remain valid even if the original object where the referenced object was constructed is destroyed.

The only concern is that the Reference_Counted_Pointer be constructed, or assigned, from its normal pointer to the shared object in a one-to-one relationship with the construction of the shared object. If the same normal pointer is used to construct, or be assigned to, more than one Reference_Counted_Pointer the Reference_Counted_Pointer objects become distinct - pointing to the same referenced object but using different reference counters - which creates a situation where one Reference_Counted_Pointer can delete the shared object while the other Reference_Counted_Pointers still hold a pointer to the now destroyed object. So equivalent, but distinct, Reference_Counted_Pointer objects should be avoided. Distinct Reference_Counted_Pointer objects can be bound together by assigning one to the other.

This implementation is based on the CountedPtr class in "The C++ Standard Library", by Nicolai M. Josuttis.

Author:
Bradford Castalia, UA/PIRL
Version:
Revision:
1.22

Constructor & Destructor Documentation

template<class T>
PIRL::Reference_Counted_Pointer< T >::Reference_Counted_Pointer ( T *  pointer = 0 ) [inline, explicit]

Construct a Reference_Counted_Pointer for a normal pointer.

The pointer argument must refer to an object that was allocated on the heap (by the new operator or equivalent).

Caution: When the same normal pointer is used to construct to more than one Reference_Counted_Pointer the two Reference_Counted_Pointers become equivalent but distinct. This should be avoided as it creates a situation where one Reference_Counted_Pointer can delete the object it refers to while the other Reference_Counted_Pointer still holds a reference to the deleted object.

Parameters:
pointerA normal pointer to be reference counted.
template<class T>
PIRL::Reference_Counted_Pointer< T >::Reference_Counted_Pointer ( const Reference_Counted_Pointer< T > &  RCP ) [inline]

Copy a Reference_Counted_Pointer.

The new Reference_Counted_Pointer object shares the normal pointer and reference counter with the object that was copied. The reference count is incremented.

Parameters:
RCPThe Reference_Counted_Pointer to be copied.
template<class T>
PIRL::Reference_Counted_Pointer< T >::~Reference_Counted_Pointer (  ) [inline]

Destroy this Reference_Counted_Pointer.

The contents are disposed of: The reference count is decremented and if it becomes zero both the pointer and counter are deleted. N.B.: Deleting the pointer will destroy the object referred to by the normal pointer.

References PIRL::Reference_Counted_Pointer< T >::dispose().


Member Function Documentation

template<class T>
Reference_Counted_Pointer<T>& PIRL::Reference_Counted_Pointer< T >::operator= ( const Reference_Counted_Pointer< T > &  RCP ) [inline]

Assign another Reference_Counted_Pointer to this Reference_Counted_Pointer.

Nothing is done if the Reference_Counted_Pointer to be assigned is the same object being assigned or is not distinct. Two Reference_Counted_Pointer objects are distinct when they refer to differenct objects - have different pointer values - or have different reference counters (counter objects, not their values).

If the two Reference_Counted_Pointers are distinct and the object they reference is different then the contents of this object are first disposed of (decrementing the reference count and possibly deleting the currently referenced object) and then the assigned Reference_Counted_Pointer's contents are copied to this object's contents. The reference count is incremented on completion of the assignment. Note that the assigned Reference_Counted_Pointer object will, of course, see its reference count increment.

N.B.: Two Reference_Counted_Pointers can be constructed from the same pointer value. But this should be avoided if at all possible as it creates a situation where the object referenced by the distinct Reference_Counted_Pointer objects may be deleted by one while the other still holds its reference. Thus a Reference_Counted_Pointer for an object should be constructed at the same point where the referenced object is constructed and then this initial Reference_Counted_Pointer used to contruct, or be assigned to, other Reference_Counted_Pointer objects as needed.

Parameters:
RCPThe Reference_Counted_Pointer to be assigned.
Returns:
This Reference_Counted_Pointer.
See also:
~Reference_Counted_Pointer()

References PIRL::Reference_Counted_Pointer< T >::dispose().

template<class T>
Reference_Counted_Pointer<T>& PIRL::Reference_Counted_Pointer< T >::operator= ( T *  pointer ) [inline]

Assign a pointer to this Reference_Counted_Pointer.

If the pointer has a different value than the pointer of this object, the contents of this object are first disposed of and then this object is reinitialized with the new pointer value and a new reference counter with a value of 1. Note that assigning a normal pointer to a Reference_Counted_Pointer that is alread bound to the same pointer does not increment the reference count.

The pointer argument must refer to an object that was allocated on the heap (by the new operator or equivalent), but must not be an array.

Caution: When the same normal pointer is assigned to more than one Reference_Counted_Pointer the two Reference_Counted_Pointers become equivalent but distinct. This should be avoided as it creates a situation where one Reference_Counted_Pointer can delete the object it refers to while the other Reference_Counted_Pointer still holds a reference to the deleted object.

Parameters:
pointerA normal pointer to be reference counted. The pointer must refer to a non-array object that was allocated on the heap.
See also:
Reference_Counted_Pointer(T*)

References PIRL::Reference_Counted_Pointer< T >::dispose().

template<class T>
T& PIRL::Reference_Counted_Pointer< T >::operator* (  ) const [inline]

Dereference this Reference_Counted_Pointer.

Returns:
A reference to the object referenced by this Reference_Counted_Pointer.
template<class T>
T* PIRL::Reference_Counted_Pointer< T >::operator-> (  ) const [inline]

Access the pointer value of this Reference_Counted_Pointer.

Returns:
A pointer to the object referenced by this Reference_Counted_Pointer.
template<class T>
PIRL::Reference_Counted_Pointer< T >::operator T * (  ) const [inline]

Get the value of the pointer held by this Reference_Counted_Pointer.

Returns:
The value of the pointer held by this Reference_Counted_Pointer.
template<class T>
PIRL::Reference_Counted_Pointer< T >::operator bool (  ) const [inline]

Test if this Reference_Counted_Pointer has a pointer with a non-NULL value.

Returns:
true if the value of this object's pointer is non-NULL; false otherwise.
template<class T>
bool PIRL::Reference_Counted_Pointer< T >::operator== ( const Reference_Counted_Pointer< T > &  RCP ) const [inline]

Test if this Reference_Counted_Pointer is equivalent to another.

Two Reference_Counted_Pointers are equivalent if the value of their normal pointers are the same.

N.B.: Two Reference_Counted_Pointers may be equivalent but also distinct from each other. This should be avoided.

Parameters:
RCPA Reference_Counted_Pointer to be compared for equality with this one.
Returns:
true if the normal pointers of both this and the other Reference_Counted_Pointer have the same value; false otherwise.
template<class T>
bool PIRL::Reference_Counted_Pointer< T >::operator!= ( const Reference_Counted_Pointer< T > &  RCP ) const [inline]

Test if this Reference_Counted_Pointer does not equal another.

Two Reference_Counted_Pointers are not equal if the value of their normal pointers are different.

Parameters:
RCPA Reference_Counted_Pointer to be compared for equality with this one.
Returns:
true if the normal pointers of both this and the other Reference_Counted_Pointer have different values; false otherwise;
See also:
operator==(const Reference_Counted_Pointer&)const
template<class T>
bool PIRL::Reference_Counted_Pointer< T >::is_distinct_from ( const Reference_Counted_Pointer< T > &  RCP ) const [inline]

Test if this Reference_Counted_Pointer is distinct from another Reference_Counted_Pointer.

Two Reference_Counted_Pointer objects are distinct when they refer to differenct objects - have different pointer values - or have different reference counters (counter objects, not their values).

N.B.: Two Reference_Counted_Pointers can refer to the same object but still be distinct. This will happen if the two objects were constructed from the same normal pointer. When two Reference_Counted_Pointers are found to be equivalent and distinct from each other, assigning one to the other will cause them to be bound together and no longer be distinct.

Parameters:
RCPA Reference_Counted_Pointer to be compared for distinctness with this one.
Returns:
true if the normal pointers of both this and the other Reference_Counted_Pointer have different values or the Reference_Counted_Pointers are using different reference counters for the same object; false otherwise;
template<class T>
long PIRL::Reference_Counted_Pointer< T >::reference_count (  ) const [inline]

Get the reference count.

Returns:
The current number of references.
template<class T>
void PIRL::Reference_Counted_Pointer< T >::dispose (  ) [inline, protected]

Dispose of the Reference_Counted_Pointer contents if no longer in use.

The reference count is decremented. If it becomes zero the reference counter and the object being referenced by the pointer are deleted.

Referenced by PIRL::Reference_Counted_Pointer< T >::operator=(), and PIRL::Reference_Counted_Pointer< T >::~Reference_Counted_Pointer().


The documentation for this class was generated from the following file: