Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members

multiptr.h

00001 /* -*- c++ -*- */
00002 /*
00003  * Expresso, a C++ Array template class library
00004  * Copyright (C) 1998,2004 Oskar Enoksson (enok@lysator.liu.se)
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public
00017  * License along with this library; if not, write to the
00018  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019  * Boston, MA  02111-1307, USA.
00020  */
00021 #ifndef EXPRESSO_MULTIPTR_HDR
00022 #define EXPRESSO_MULTIPTR_HDR
00023 
00024 namespace esso {
00025 
00026   template<class T>
00027   struct MultiPtr_Block {
00028     inline T *Data() { return data; }
00029       
00030     inline void Attach() { ++counter; }
00031     inline void Detach() { if(--counter==0) delete this; }
00032       
00033     inline MultiPtr_Block(unsigned size0): counter(0), data(0) {
00034       data=new T[size0];
00035     }
00036     inline ~MultiPtr_Block() { delete [] data; }
00037   protected:
00038     unsigned counter;
00039     T *data;
00040   };
00041 
00043 // MultiPtr class template definition
00044   template<class T>
00045   class MultiPtr {
00046 // Class that keeps track of dynamically allocated memory used by
00047 // one or more other objects. The idea is that the data in a
00048 // MultiPtr::Block is destroyed when (and only when) the last MultiPtr
00049 // pointing to it is destroyed. This is done by reference counting
00050   private:
00051   public:
00052     friend class MultiPtr<const T>;
00053     inline T * Data() const { return block ? block->Data() : 0; }
00054     inline void clear() {
00055       if(block) {
00056         block->Detach();
00057         block = 0;
00058       }
00059     }
00060     inline MultiPtr & operator =(const MultiPtr &src) {
00061       MultiPtr_Block<T> *tmp=block; // Self-assignment is safe!
00062       block=src.block;
00063       if(block)
00064         block->Attach();
00065       if(tmp)
00066         tmp->Detach();
00067       return *this;
00068     }
00069     inline MultiPtr(): block(0) {}
00070     inline MultiPtr(unsigned size0): block(0) { 
00071       if(size0) {
00072         block = new MultiPtr_Block<T>(size0);
00073         block->Attach(); 
00074       }
00075     }
00076     inline MultiPtr(const MultiPtr &src): block(src.block) { 
00077       if(block) block->Attach();
00078     }
00079     inline ~MultiPtr() { if(block) block->Detach(); }
00080   private:
00081     MultiPtr_Block<T> *block;
00082   };
00083 
00084   template<class T>
00085   class MultiPtr<const T> {
00086   public:
00087     inline const T * Data() const { return block ? block->Data(): 0; }
00088     inline void clear() {
00089       if(block) {
00090         block->Detach();
00091         block = 0;
00092       }
00093     }
00094     inline MultiPtr & operator =(const MultiPtr &src) {
00095       MultiPtr_Block<T> *tmp=block; // Self-assignment is safe!
00096       block=src.block;
00097       if(block)
00098         block->Attach();
00099       if(tmp)
00100         tmp->Detach();
00101       return *this;
00102     }
00103     inline MultiPtr & operator =(const MultiPtr<T> &src) {
00104       MultiPtr_Block<T> *tmp=block; // Self-assignment is safe!
00105       block=src.block;
00106       if(block)
00107         block->Attach();
00108       if(tmp)
00109         tmp->Detach();
00110       return *this;
00111     }
00112     inline MultiPtr(): block(0) {}
00113     inline MultiPtr(unsigned size0): block(0) { 
00114       if(size0) {
00115         block = new MultiPtr_Block<T>(size0);
00116         block->Attach(); 
00117       }
00118     }
00119     inline MultiPtr(const MultiPtr &src): block(src.block) { 
00120       if(block) block->Attach(); 
00121     }
00122     inline MultiPtr(const MultiPtr<T> &src): block(src.block) { 
00123       if(block) block->Attach(); 
00124     }
00125     inline ~MultiPtr() { if(block) block->Detach(); }
00126   private:
00127     MultiPtr_Block<T> *block;
00128   };
00129 
00130 }
00131 #endif

Generated on Wed May 12 13:34:34 2004 for Expresso by doxygen 1.3.3