Managed Pointers

These classes provide an infrastructure to suport pointer management. Using reference counting, users can wrap a pointer so as to provide a concrete object with either reference- or value-semantics. Feel free to use/modifiy this code -- an attribution is always nice.

The syntax coloring for this page was performed by vim, the powerful cross-platform editor. www.vim.org.


// Author: Dave Whipp, mailto:dave@whipp.name
// Date: March 2000
// Company: Infineon Technologies Corp.


ManagedRepresentation.h

#ifndef _utilities__ManagedRepresentation_h #define _utilities__ManagedRepresentation_h //#include "utilities/FastAllocate.h" namespace utilities { class ManagedRepresentation // : public FastAllocate { public: ManagedRepresentation(); virtual ~ManagedRepresentation(); void removeReference(); void addReference(); int getReferenceCount() const; private: unsigned int _ref_count; }; } #endif


ManagedRepresentation.cpp

#include "ManagedRepresentation.h" #include typeinfo> #include iostream> using namespace utilities; ManagedRepresentation::ManagedRepresentation() : _ref_count(1) {} ManagedRepresentation::~ManagedRepresentation() { if (_ref_count--) { cerr << "warning: dtor with non-zero ref count in ManagedRepresentation. are you using a stack-based variable?" << endl; } // ref count is -1! (might catch multiple deletions) } void ManagedRepresentation::removeReference() { if (--_ref_count == 0) delete this; } void ManagedRepresentation::addReference() { ++_ref_count; } int ManagedRepresentation::getReferenceCount() const { return _ref_count; }


ManagedPointer.h

#ifndef _utilities__ManagedPointer_h #define _utilities__ManagedPointer_h namespace utilities { template<class T> class ValueObject; template<class T> class ManagedPointer { public: ManagedPointer(); ManagedPointer(T* arg); ManagedPointer(const ManagedPointer& arg); virtual ~ManagedPointer(); void assign(const ManagedPointer& arg); const T& query() const; T& modify(); private: mutable T* _rep; friend class ValueObject; }; template<class T> inline ManagedPointer::ManagedPointer() : _rep(new T) {} template<class T> inline ManagedPointer::ManagedPointer(T* arg) : _rep(arg) {} template<class T> inline ManagedPointer::ManagedPointer(const ManagedPointer& arg) : _rep(arg._rep) { _rep->addReference(); } template<class T> inline void ManagedPointer::assign(const ManagedPointer& arg) { if (this != &arg) { _rep->removeReference(); arg._rep->addReference(); _rep = arg._rep; } } template<class T> inline ManagedPointer::~ManagedPointer() { _rep->removeReference(); } template<class T> inline const T& ManagedPointer::query() const { return *_rep; } template<class T> inline T& ManagedPointer::modify() { return *_rep; } } #endif


ValueObject.h

#ifndef _utilities__ValueObject_h #define _utilities__ValueObject_h #include "utilities/ManagedPointer.h" namespace utilities { template<class T> class ValueObject : public ManagedPointer { public: ValueObject(); ValueObject(T* arg); ValueObject(const ValueObject& arg); T& modify(); }; template<class T> inline ValueObject::ValueObject() : ManagedPointer(new T) {} template<class T> inline ValueObject::ValueObject(T* arg) : ManagedPointer(arg) {} template<class T> inline ValueObject::ValueObject(const ValueObject& arg) : ManagedPointer(arg) {} template<class T> inline T& ValueObject::modify() { if (_rep->getReferenceCount() > 1) { _rep->removeReference(); _rep=_rep->clone(); } return *_rep; } } #endif


test_ManagedRepresentation.cpp

#include "test_support.h" #include "ManagedRepresentation.h" #include "ManagedPointer.h" #include "ValueObject.h" using namespace utilities; class Representation : public ManagedRepresentation { public: Representation(int v) : ManagedRepresentation(), _value(v) {} Representation(const Representation& arg) : ManagedRepresentation(), _value(arg._value) {} Representation* clone() { return new Representation(*this); } int getValue() const { return _value; } void setValue(int v) {_value = v;} private: int _value; }; class Pointer : public ManagedPointer { public: Pointer(int v) : ManagedPointer(new Representation(v)) {} Pointer(const Pointer& arg) : ManagedPointer(arg) {} Pointer& operator=(const Pointer& arg) {assign(arg); return *this;} int getValue() const {return query().getValue();} void setValue(int v) {modify().setValue(v);} }; class Value : public ValueObject { public: Value(int v) : ValueObject(new Representation(v)) {} Value(const Value& arg) : ValueObject(arg) {} Value& operator=(const Value& arg) {assign(arg); return *this;} int getValue() const {return query().getValue();} void setValue(int v) {modify().setValue(v);} }; void test_Pointer() { Pointer p1(1); Pointer p2(2); TEST_EQUAL(p1.getValue(), 1) TEST_EQUAL(p2.getValue(), 2) Pointer p3(-1); p3=p1; TEST_EQUAL(p3.getValue(), 1) p3.setValue(3); TEST_EQUAL(p3.getValue(), 3) TEST_EQUAL(p1.getValue(), 3) Pointer p4(p1); TEST_EQUAL(p4.getValue(), 3) p4.setValue(4); TEST_EQUAL(p4.getValue(), 4) TEST_EQUAL(p1.getValue(), 4) } void test_Value() { Value v1(11); Value v2(22); TEST_EQUAL(v1.getValue(), 11) TEST_EQUAL(v2.getValue(), 22) Value v3=33; TEST_EQUAL(v3.getValue(), 33) v3=v1; TEST_EQUAL(v3.getValue(), 11) v3.setValue(33); TEST_EQUAL(v3.getValue(), 33) TEST_EQUAL(v1.getValue(), 11) Value v4(v1); TEST_EQUAL(v4.getValue(), 11) v4.setValue(44); TEST_EQUAL(v4.getValue(), 44) TEST_EQUAL(v1.getValue(), 11) } void test_ManagedRepresentation() { test_Pointer(); test_Value(); }


test_support.h

#include iostream> #include stdexcept> extern int error_count; #ifdef DEBUG #define DEBUG_OUT(x,y) {std::cerr << "DEBUG: " << __FILE__ << " [" << (__LINE__) << "] : " << #x << " " << y << std::endl;} #else #define DEBUG_OUT(x,y) #endif #define FAIL(x) { error_count++; std::cerr << "ERROR: " << __FILE__ << " [" << (__LINE__) << "] : " << x << std::endl;} #define TEST(x) { DEBUG_OUT(TEST, #x) if (!(x)) FAIL(#x)} #define TEST_EQUAL(x,y) { DEBUG_OUT(TEST_EQUAL, #x << "," << #y) if ((x) != (y)) FAIL(#x << " == " << #y << " (" << (x) << " != " << (y) << ")") } #define TEST_CATCH(e,x) { DEBUG_OUT(TEST_CATCH, #e) try { {x;} FAIL("exception (" << #e << ") not thrown: " << #x) } catch (e) {} }

comments: mailto:dave@whipp.name
last modified: 26 May 2000
home