OA_ptr.hpp

Go to the documentation of this file.
00001 
00012 #ifndef OAPTR_H
00013 #define OAPTR_H
00014 
00015 #include <iostream>
00016 #include <cassert>
00017 #include <set>
00018 #include "Util.hpp"
00019 
00020 static bool OA_ptr_debug = false;
00021 
00022 namespace OA {
00023 
00024 template <class T>
00025 class OA_ptr {
00026   public:
00027     OA_ptr() : mPtr(NULL), mRefCountPtr(NULL)  { }
00028     /*
00029   private:
00030     OA_ptr(T* ptr) : mPtr(ptr), mRefCountPtr(NULL)
00031         { if (ptr!=NULL) {
00032               mRefCountPtr = new int;
00033               *mRefCountPtr = 1;
00034           }
00035         }
00036         */
00037   public:
00039     OA_ptr(const OA_ptr<T> &other) 
00040         : mPtr(other.mPtr), mRefCountPtr(other.mRefCountPtr)
00041     {
00042         if (OA_ptr_debug) { std::cout << "OA_ptr copy constructor: other = ";
00043                      other.dump(std::cout);  std::cout << std::endl; }
00044         if (mRefCountPtr!=NULL) 
00045         { (*mRefCountPtr)++; }
00046     }
00047 
00049     OA_ptr<T>& operator= (T* ptr)
00050     {
00051         // don't do anything for self-assignment
00052         if (mPtr != ptr) {
00053             decrementCurrPtr();
00054             mPtr = ptr;
00055             // do not need to reference count NULL, make new ref counter
00056             // if getting a ptr other than NULL and if getting NULL
00057             // set mRefCountPtr to NULL            
00058             if (mPtr != NULL) {              
00059                 mRefCountPtr = new int;              
00060                 *mRefCountPtr = 1;            
00061             } else {
00062                 mRefCountPtr = NULL;
00063             }
00064         }
00065         return *this;
00066      }
00067 
00069     OA_ptr<T>& operator= (const OA_ptr<T> &other)
00070     {
00071         // don't do anything for self-assignment
00072         if (mPtr != other.mPtr) {
00073             decrementCurrPtr();
00074             mPtr = other.mPtr;
00075             // do not need to reference count NULL, make new ref counter
00076             // if getting a ptr other than NULL and if getting NULL
00077             // set mRefCountPtr to NULL            
00078             mRefCountPtr = other.mRefCountPtr;
00079             if (mPtr != NULL) {              
00080                 (*mRefCountPtr)++;            
00081             } 
00082         }
00083         return *this;
00084      }
00085 
00086   // this doesn't work properly:
00087 //     //! copy assignment
00088 //     template <class T2>
00089 //     OA_ptr<T>& operator= (const OA_ptr<T2> &other)    
00090 //     {
00091 //         // don't do anything for self-assignment
00092 //         if (this != dynamic_cast<const OA_ptr<T>* >(&other)) {
00093 //             mPtr = (dynamic_cast<const OA_ptr<T>& >(other)).mPtr;
00094 //             mRefCountPtr = (dynamic_cast<const OA_ptr<T>& >(other)).mRefCountPtr;
00095 //             if (mRefCountPtr!=NULL) { (*mRefCountPtr)++; }
00096 //         }
00097  
00098 //        return *this;
00099 //     } 
00100 
00101     virtual ~OA_ptr() 
00102     { 
00103         decrementCurrPtr();
00104     }
00105 
00106     T* operator->() const
00107     {
00108         assert(mPtr != NULL);
00109         return mPtr;
00110     }
00111 
00112     T& operator*() const
00113     {
00114         assert(mPtr != NULL);
00115         return *mPtr;
00116     }
00117 
00118     // constructor used by convert, can't be private because convert
00119     // calls it on the OA_ptr<T2> and T1=T2
00120     OA_ptr(T* ptr, int* countPtr) 
00121         : mPtr(ptr), mRefCountPtr(countPtr)
00122     {
00123         assert((ptr==0&&countPtr==0) || (ptr!=0&&countPtr!=0));
00124         if (OA_ptr_debug) { std::cout << "OA_ptr constructor ptr,cnt: ptr = ";
00125             //std::cout << mPtr << ", countPtr = " << countPtr << std::endl; 
00126         }
00127         if (mRefCountPtr!=NULL) { (*mRefCountPtr)++; }
00128         if (OA_ptr_debug) { std::cout << "OA_ptr constructor ptr,cnt: *this = ";
00129                      dump(std::cout);  std::cout << std::endl; }
00130      }
00131           
00132     // enables us to do dynamic casts
00133     template <class T2>
00134     OA_ptr<T2> convert() const
00135     {
00136         assert(mPtr != NULL);
00137         T2* retval = dynamic_cast<T2*>(mPtr);
00138         assert(retval != NULL);
00139         return OA_ptr<T2>(retval,mRefCountPtr);
00140     }
00141     
00142     // enables us to do some RTTI
00143     template <class T2>
00144     bool isa() const
00145     {
00146         assert(mPtr != NULL);
00147         T2* retval = dynamic_cast<T2*>(mPtr);
00148         if (retval==NULL) {
00149             return false;
00150         } else {
00151             return true;
00152         }
00153     }
00154 
00155 
00156     // so that can pass a subclass into base class
00157     // Stroustrup 349-350
00158     template <class T2> operator OA_ptr<T2> () const 
00159         { return OA_ptr<T2>(mPtr,mRefCountPtr); }
00160         
00161     bool ptrEqual(const T* rhs) const
00162         {
00163             return mPtr == rhs;
00164         }
00165     bool ptrEqual(const OA_ptr& other) const
00166         {
00167             return mPtr == other.mPtr;
00168         }
00169 
00170 
00171     bool operator==(const OA_ptr<T>& other) const 
00172         {
00173           bool retval;
00174           
00175           if (OA_ptr_debug) {
00176             std::cout << "In OA_ptr::operator==" << std::endl; 
00177             std::cout << "\t*this=";
00178             dump(std::cout);
00179             std::cout << ", other=";
00180             other.dump(std::cout);
00181             dump(std::cout);
00182           }
00183 
00184           if (mPtr==other.mPtr) {
00185             retval = true;
00186           } else if (mPtr==0 || other.mPtr==0) {
00187             retval = false;
00188           } else {
00189             retval = *mPtr==*(other.mPtr); 
00190           }
00191           if (OA_ptr_debug) {
00192             std::cout << "\nOA_ptr::operator== returning " << retval 
00193                       << std::endl;
00194           }
00195           return retval;
00196         }
00197 
00198     template <class T2>
00199     bool operator==(const OA_ptr<T2>& other) const 
00200         {
00201           bool retval;
00202           
00203           if (OA_ptr_debug) {
00204             std::cout << "In OA_ptr::operator==(T2)" << std::endl; 
00205             std::cout << "\t*this=";
00206             dump(std::cout);
00207             std::cout << ", other=";
00208             other.dump(std::cout);
00209             dump(std::cout);
00210           }
00211 
00212           if (ptrEqual(0) && other.ptrEqual(0)) {
00213             retval = true;
00214           } else if (ptrEqual(0) || other.ptrEqual(0)) {
00215             retval = false;
00216           } else {
00217             retval = *mPtr==*other; 
00218           }
00219           if (OA_ptr_debug) {
00220             std::cout << "\tOA_ptr::operator== returning " << retval 
00221                       << std::endl;
00222           }
00223           return retval;
00224         }
00225 
00226 
00227     bool operator!=(const OA_ptr<T>& other)  const 
00228         {
00229           return ! (*this==other); 
00230         }
00231 
00232     template <class T2>
00233     bool operator!=(const OA_ptr<T2>& other) const 
00234         {
00235           return ! (*this==other); 
00236         }
00237 
00238 
00244     bool operator<(const OA_ptr<T>& other)  const 
00245         { 
00246           bool retval;
00247 
00248           if (OA_ptr_debug) {
00249             std::cout << "In OA_ptr::operator<" << std::endl; 
00250             std::cout << "\t*this=";
00251             dump(std::cout);
00252             std::cout << ", other=";
00253             other.dump(std::cout);
00254             std::cout << std::endl;
00255           }
00256 
00257           // if both objects are equal then return false
00258           if ( mPtr==other.mPtr 
00259                || other.mPtr == 0
00260                || *mPtr==*(other.mPtr) ) 
00261           {
00262               retval = false;
00263 
00264           // if the first one is null and other wasn't then less than
00265           } else if ( mPtr==0 ) {
00266               retval = true;
00267 
00268           // if the second one is null and first one wasn't then greater
00269           } else if ( mPtr==0 ) {
00270               retval = false;
00271 
00272           // if the objects are not equal then call operator< on them
00273           } else {
00274               retval = *mPtr<*(other.mPtr); 
00275           }
00276           if (OA_ptr_debug) {
00277             std::cout << "\tOA_ptr::operator< returning " << retval 
00278                       << std::endl; 
00279           }
00280           return retval;
00281         }
00282 
00283     template <class T2>
00284     bool operator<(const OA_ptr<T2>& other)  const 
00285         { 
00286           bool retval;
00287           if (ptrEqual(0) && other.ptrEqual(0)) {
00288               retval = false;
00289           // if the first one is null and other wasn't then less than
00290           } else if (ptrEqual(0) ) {
00291               retval = true;
00292           // if the second one is null and first wasn't then greater than
00293           } else if (other.ptrEqual(0) ) {
00294               retval = false;
00295 
00296           } else { retval = *mPtr<*(other); }
00297           return retval;
00298         }
00299 
00300 
00301     void dump(std::ostream& os) const 
00302         { //os << "OA_ptr(mPtr = " << mPtr << ", *mRefCountPtr="; // IRIX compiler?
00303           os << "OA_ptr(mPtr = " << ", *mRefCountPtr=";
00304           os.flush();
00305           if (mRefCountPtr!=NULL) { os << *mRefCountPtr; }
00306           else { os << 0; }
00307           os << ")";
00308         }
00309 
00310     inline friend std::ostream& operator <<(std::ostream & out, 
00311                                             const OA_ptr<T>& oaptr)
00312         {
00313             oaptr.dump(out);
00314             return out;
00315         }
00316 
00317   private:
00318     T* mPtr;
00319     int* mRefCountPtr;
00320 
00321   private:
00323     void decrementCurrPtr()
00324     {
00325         if (mPtr!=NULL) {
00326             //assert(mRefCountPtr!=NULL);
00327             //FIXME: sometimes can get here and have mRefCountPtr==NULL, how?
00328             //and mPtr be unitialized
00329             if (mRefCountPtr!=NULL) {
00330               (*mRefCountPtr)--;
00331               if (*mRefCountPtr == 0) {
00332                 delete mPtr;
00333                 delete mRefCountPtr;
00334               }
00335             }
00336         }
00337         // no matter what should not have mPtr or mRefCountPtr at this point
00338         mPtr = NULL;
00339         mRefCountPtr = NULL;
00340     }
00341 
00342 };
00343 
00344 } // end of OA namespace
00345 
00346 #endif

Generated on Sat Oct 31 05:21:25 2009 for OpenAnalysis by  doxygen 1.6.1