Molmodel

GrinPointer.h

Go to the documentation of this file.
00001 /* GrinPointer.h */
00002 
00003 /* Portions copyright (c) 2007 Stanford University and Christopher M. Bruns.
00004  * Contributors:
00005  *
00006  * Permission is hereby granted, free of charge, to any person obtaining
00007  * a copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sublicense, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject
00012  * to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIdED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00019  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00020  * IN NO EVENT SHALL THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE
00021  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00022  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00023  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00024  */
00025 
00026 #ifndef SimTK_QUALIFIEDSMARTPOINTER_H_
00027 #define SimTK_QUALIFIEDSMARTPOINTER_H_
00028 
00029 #include "Clonable.h"
00030 
00031 // Templated class that uses semantics of a pointer.
00032 // Used as a helper class in the "Cheshire Cat", or PIMPL,
00033 // paradigm used to separate interface from implementation in 
00034 // C++.  
00035 
00036 // Very similar to grin_ptr<> class by Alan Griffiths
00037 // http://www.octopull.demon.co.uk/arglib/TheGrin.html
00038 
00039 // Uses concept of qualified smart pointer from 
00040 // Kevlin Henney ("Coping with Copying in C++" - Overload 33 ISSN 1354 3172)
00041 
00042 // "Qualified" means that the access operators, operator* and
00043 // operator->, are overloaded with respect to const-ness, so
00044 // their results follow the const qualification.
00045 
00046 // From Alan Griffiths' article:
00047 // http://accu.org/index.php/journals/482
00048 // 
00049 //        "Let us start with the last point mentioned in the discussion of auto_ptr<>
00050 //        - how to cope with deleting an incomplete type. The destructor can't be a 
00051 //        simple "delete p;" because at the point of instantiation the pointer is to 
00052 //        an "incomplete type" and the compiler won't call the destructor.
00053 //
00054 //        To avoid this I make use of the fact that the constructor for grin_ptr<> 
00055 //        is instantiated in the implementation file, where the class definition for 
00056 //        implementation resides. At this point I force the compiler to generate a 
00057 //        deletion function using a trick I first saw in Richard Hickey's article 
00058 //        "Callbacks in C++ Using Template Functors" (C ++ Gems ISBN 1 884842 37 2): 
00059 //        the constructor stores a pointer to this function in the grin_ptr<>. This 
00060 //        provides a safe method for the destructor to delete the object it owns. 
00061 //        The point of passing around function pointers instead of the apparently 
00062 //        more natural use of virtual member functions is that everything can be 
00063 //        done "by value" and no dynamic allocation is required.
00064 //
00065 //        A similar function is used for copying the object..."
00066 
00067 namespace SimTK {
00068 
00069 // Overloaded deepCopy() methods will use "clone()" method if 
00070 // referent is derived from Clonable.  Otherwise it calls new
00071 // with its copy constructor, which should work for non-derived
00072 // classes
00073 
00074 // Fallback deep copy for non-Clonable objects
00075 template<class PointeeType>
00076 inline PointeeType* deepCopy(const PointeeType* ptr, const void*) 
00077 {
00078     return ptr ? new PointeeType(*ptr) : 0;
00079 }
00080 
00081 // Deep copy for objects that derive from Clonable
00082 template<class PointeeType>
00083 inline PointeeType* deepCopy(const PointeeType *ptr, const Clonable *)
00084 {
00085     return ptr ? ptr->clone() : 0;
00086 }
00087 
00088 // At instantiation time, this method will decide which of the above to use.
00089 template<class PointeeType>
00090 inline PointeeType* deepCopy(const PointeeType* ptr) 
00091 {
00092     return deepCopy(ptr, ptr);
00093 }
00094 
00095 
00096 template<typename PointeeType>
00097 class GrinPointer {
00098 public:
00099     explicit GrinPointer(PointeeType* pointee)
00100          : doCopy(&myCopyFunction), ptr(pointee), doDelete(&myDeleteFunction) 
00101     {
00102         // doCopy = &myCopyFunction;
00103         // ptr = pointee;
00104         // doDelete = &myDeleteFunction;
00105     }
00106 
00107     GrinPointer(const GrinPointer & src);
00108 
00109     ~GrinPointer() throw() { doDelete(ptr); }
00110 
00111     const PointeeType* operator->() const {return ptr;}
00112     PointeeType* operator->() {return ptr;}
00113 
00114     const PointeeType& operator*() const {return *ptr;}
00115     PointeeType& operator*() {return *ptr;}
00116 
00117     GrinPointer& operator=(const GrinPointer& src);
00118 
00119 private:
00120     typedef void (*DeleteFunctionPtr)(PointeeType* ptr);
00121     typedef PointeeType* (*CopyFunctionPtr)(const PointeeType* ptr);
00122 
00123     CopyFunctionPtr doCopy;
00124     PointeeType* ptr;
00125     DeleteFunctionPtr doDelete;
00126 
00127     static void myDeleteFunction(PointeeType* ptr) {
00128         delete ptr;
00129     }
00130     static PointeeType*  myCopyFunction(const PointeeType* ptr) {
00131         return deepCopy(ptr);
00132     }
00133 
00134 };
00135 
00136 // Deep copy uses clone() method if wrapped type inherits the
00137 // "Clonable" interface.
00138 
00139 template<typename PointeeType>
00140 inline GrinPointer<PointeeType>::GrinPointer(const GrinPointer& src)
00141 :
00142     doCopy(src.doCopy),
00143     ptr(doCopy(src.ptr)),
00144     doDelete(src.doDelete)
00145 {}
00146     
00147 template<typename PointeeType>
00148 inline GrinPointer<PointeeType>& GrinPointer<PointeeType>::operator=(const GrinPointer& src)
00149 {
00150     // Allocate...
00151     PointeeType* tmp = doCopy(src.ptr);
00152 
00153     // ...before release...
00154     doDelete(ptr);
00155 
00156     // ...and update
00157     ptr = tmp;
00158     return *this;
00159 }
00160 
00161 }
00162 
00163 #endif // SimTK_QUALIFIEDSMARTPOINTER_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines