From 76358abd3af065dda7f8335ad2eb415c78c6eaa3 Mon Sep 17 00:00:00 2001 From: Markus Blatt <mblatt@dune-project.org> Date: Tue, 2 Nov 2004 11:07:28 +0000 Subject: [PATCH] Added a reference counting pointer with test. [[Imported from SVN: r1014]] --- common/smartpointer.hh | 109 ++++++++++++++++++++++++++++++++ common/test/.gitignore | 3 +- common/test/Makefile.am | 4 +- common/test/smartpointertest.cc | 51 +++++++++++++++ 4 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 common/smartpointer.hh create mode 100644 common/test/smartpointertest.cc diff --git a/common/smartpointer.hh b/common/smartpointer.hh new file mode 100644 index 000000000..776a2e26e --- /dev/null +++ b/common/smartpointer.hh @@ -0,0 +1,109 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +// $Id$ + +#ifndef __DUNE_SMARTPOINTER_HH__ +#define __DUNE_SMARTPOINTER_HH__ + +/** + * @file + * @brief This file implements the class SmartPointer which is a reference counting + * pointer. + * @author Markus Blatt + */ +namespace Dune { + + /** + * @brief A reference counting smart pointer. + * + * It is designed such that it is usable within a std::vector. + * The contained object is destroyed only if there are no more + * references to it. + */ + template<class T> + class SmartPointer { + public: + /** + * @brief The data type we are a pointer for. + * + * This has to have a parameterless constructor. + */ + typedef T MemberType; + + /** + * @brief Constructs a new smart pointer and allocates the referenced Object. + */ + inline SmartPointer(); + + /** + * @brief Copy constructor. + * @param pointer The object to copy. + */ + inline SmartPointer(const SmartPointer& pointer); + + /** + * @brief Destructor. + */ + inline ~SmartPointer(); + + inline SmartPointer& operator=(const SmartPointer& pointer); + + inline MemberType& operator*(); + + inline MemberType* operator->(); + + int count(); + private: + /** @brief The object we reference. */ + class PointerRep { + friend class SmartPointer<MemberType>; + /** @brief The number of references. */ + int count_; + /** @brief The representative. */ + MemberType rep_; + /** @brief Constructor. */ + PointerRep(const MemberType& rep) : count_(1), rep_(rep){} + } *rep_; + }; + + template<class T> + inline SmartPointer<T>::SmartPointer(){ + rep_ = new PointerRep(MemberType()); + } + + template<class T> + inline SmartPointer<T>::SmartPointer(const SmartPointer<T>& other) : rep_(other.rep_){ + ++(rep_->count_); + } + + template<class T> + inline SmartPointer<T>& SmartPointer<T>::operator=(const SmartPointer<T>& other){ + (other.rep_->count_)++; + if(--(rep_->count_)<=0) delete rep_; + rep_ = other.rep_; + return *this; + } + + template<class T> + inline SmartPointer<T>::~SmartPointer(){ + if(--(rep_->count_)<=0) { + delete rep_; + } + } + + template<class T> + inline T& SmartPointer<T>::operator*(){ + return rep_->rep_; + } + + template<class T> + inline T *SmartPointer<T>::operator->(){ + return &(rep_->rep_); + } + + template<class T> + inline int SmartPointer<T>::count(){ + return rep_->count_; + } +} +#endif diff --git a/common/test/.gitignore b/common/test/.gitignore index 31b9864db..ab73500fa 100644 --- a/common/test/.gitignore +++ b/common/test/.gitignore @@ -5,4 +5,5 @@ Makefile.in semantic.cache parsetest test-stack -arraylisttest \ No newline at end of file +arraylisttest +smartpointertest \ No newline at end of file diff --git a/common/test/Makefile.am b/common/test/Makefile.am index f0fd04638..eb1bd5968 100644 --- a/common/test/Makefile.am +++ b/common/test/Makefile.am @@ -1,6 +1,6 @@ # $Id$ -TESTPROGS = parsetest test-stack arraylisttest +TESTPROGS = parsetest test-stack arraylisttest smartpointertest # which tests to run TESTS = $(TESTPROGS) @@ -15,3 +15,5 @@ parsetest_SOURCES = parsetest.cc test_stack_SOURCES = test-stack.cc arraylisttest_SOURCES = arraylisttest.cc + +smartpointertest_SOURCES = smartpointertest.cc diff --git a/common/test/smartpointertest.cc b/common/test/smartpointertest.cc new file mode 100644 index 000000000..813ef3752 --- /dev/null +++ b/common/test/smartpointertest.cc @@ -0,0 +1,51 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +// $Id$ + +#include <dune/common/smartpointer.hh> +#include <iostream> +#include <vector> + +int main(){ + using namespace Dune; + int ret=0; + { + SmartPointer<double> b; + { + SmartPointer<double> d(b); + *b = 7; + } + if(b.count()!=1) { + std::cout << "Reference count is wrong! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + { + SmartPointer<double> c(b); + + if(*b!=*c) { + std::cerr<<"References do not match! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + if(b.count()!=2 || c.count()!=2) { + std::cout << "Reference count is wrong! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + *b=8; + if(*b!=8 || *c!=8) { + std::cout<<"Assigning new value failed! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + } + + if(b.count()!=1) { + std::cout << "Reference count is wrong! "<<__LINE__<<":"<< + __FILE__<<std::endl; + ret=1; + } + } + exit(ret); +} -- GitLab