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

rc_ptrs.h

00001 // Copyright (C) 2001 Jean-Marc Valin
00002 
00003 #ifndef __RC_PTRS_H
00004 #define __RC_PTRS_H
00005 
00006 #ifdef _MSC_VER
00007 #pragma warning (disable: 4786)
00008 #endif
00009 
00010 /*
00011  * Copyright 1998
00012  * Mark E. (snowball3@usa.net)
00013  * http://members.xoom.com/snowball3/cpp/
00014  *
00015  * Permission to use, copy, modify, and distribute this software
00016  * and its documentation for any purpose is hereby granted without fee,
00017  * provided that the above copyright notice appear in all copies and
00018  * that both that copyright notice and this permission notice appear
00019  * in supporting documentation.
00020  *
00021  * Mark E. makes no representations about the suitability of
00022  * this software for any purpose. It is provided "as is" without
00023  * express or implied warranty.
00024  *
00025  */
00026 
00027 /*
00028    Since then, heavily modified by Jean-Marc Valin (1999)
00029    valj01@gel.usherb.ca
00030 */
00031 
00032 
00033 
00034 #include <stddef.h>
00035 #include <iostream>
00036 #include <typeinfo>
00037 #include "BaseException.h"
00038 #include <string>
00039 
00040 #ifdef WIN32 /*Work around bug in MSVC++ (for) variable scope*/
00041 #define for if(0);else for
00042 #endif
00043 
00044 namespace FD {
00045 
00052 template <class T, class U>
00053 class PtrCastException : public GenericCastException {
00054 protected:
00055         std::string type;
00056 public:
00058    PtrCastException(const T *obj)
00059       : type(typeid(*obj).name())
00060    {}
00061   
00063    virtual void print(std::ostream &out = std::cerr) 
00064    {
00065       out << "Cast error: Trying to cast RCPtr <" << typeid(T).name() << "> (" 
00066           << type << ") into RCPtr<" << typeid(U).name() << ">" << std::endl;
00067    }
00068 };
00069 
00070 class PtrException : public BaseException {
00071 protected:
00072         std::string message;
00073 public:
00075    PtrException(const std::string &_message)
00076       : message(_message)
00077    {}
00078   
00080    virtual void print(std::ostream &out = std::cerr) 
00081    {
00082       out << message << std::endl;
00083    }
00084 };
00085 
00086 
00092 template <class X>
00093 class RCPtr
00094 {
00095 public:
00096    typedef X element_type;
00097    typedef X* pointer_type;
00098    typedef size_t size_type;
00099 
00100 #ifndef BROKEN_TEMPLATES
00101 protected:
00102 #endif
00103    X* ptr;
00104    //size_type *count;
00105    
00106 
00107 public:
00108    explicit RCPtr(X* p=0) : ptr(p)
00109    {
00110       //count=new size_type(1);
00111    }
00112 
00113    bool isNil() {return ptr == 0;}
00114 
00115    template <class Z>
00116      RCPtr(const RCPtr<Z> &r);
00117 
00118    /*{
00119      cerr << "RCPtr(const RCPtr<Z> &r)" << std::endl;
00120       ptr=dynamic_cast<X*> (r.ptr);
00121       if (!ptr) 
00122          {
00123             //throw "RCPtr<X>: Illegal pointer conversion in copy constructor";
00124             if (!ptr) throw new PtrCastException<Z,X>(r.ptr);
00125          }
00126       //count=r.count;
00127       acquire();
00128       }*/
00129    
00130    RCPtr(const RCPtr<X> &r)
00131    {
00132       ptr=r.ptr;
00133       //count=r.count;
00134       acquire();
00135    }
00136    
00137    ~RCPtr() { release(); }
00138    
00139 
00140    template <class Z>
00141    RCPtr& operator= (const RCPtr<Z> &r)
00142       ;/*{
00143       if ((int) this != (int) (&r))
00144       {
00145          X *tmp=dynamic_cast<X*> (r.ptr);
00146          //if (!tmp) throw "RCPtr<X>: Illegal pointer conversion in operator =";
00147          if (!tmp) throw new PtrCastException<Z,X>(r.ptr);
00148          release();
00149          ptr=tmp;
00150          //count = r.count;
00151          acquire();
00152       }
00153       return *this;
00154       }*/
00155 
00156    RCPtr& operator= (const RCPtr<X> &r)
00157    {
00158       if (this != &r)
00159       {
00160          release();
00161          ptr = r.ptr;
00162          //count = r.count;
00163          acquire();
00164       }
00165       return *this;
00166    }
00167 
00168    template <class Z>
00169    RCPtr& operator= (Z *r)
00170    {
00171       if ((int) ptr != (int) (r))
00172       {
00173          X *tmp=dynamic_cast<X*> (r);
00174          //if (!tmp) throw "RCPtr<X>: Illegal pointer conversion in operator =";
00175          if (!tmp) throw new PtrCastException<Z,X>(r);
00176          release();
00177          ptr=tmp;
00178          //count=new size_type(1);
00179       }
00180       return *this;
00181    }
00182 
00183    RCPtr& operator= (X *r)
00184    {
00185       if (ptr != r)
00186       {
00187          release();
00188          ptr = r;
00189          //count=new size_type(1);
00190       }
00191       return *this;
00192    }
00193 
00194 #ifdef RT_DEBUG
00195    X& operator* () const {if (ptr) return *ptr; else throw new PtrException("dereferencing NULL pointer in operator*");}
00196    X* operator->() const {if (ptr) return  ptr; else throw new PtrException("dereferencing NULL pointer in operator->");}
00197 #else
00198    X& operator* () const {return *ptr; }
00199    X* operator->() const {return  ptr; }
00200 #endif
00201    X* get () const { return ptr;}
00202 
00203    bool unique () const
00204    {
00205       return (ptr && ptr->unique());
00206    }
00207 
00208    X *detach () 
00209    {
00210       if (ptr)
00211       {
00212          if (ptr->unique()) 
00213          {
00214             X *tmp = ptr;
00215             ptr = 0;
00216             return tmp;
00217          } else {
00218             throw new PtrException("Error: trying to detach a non-unique pointer in rc_ptrs.h");
00219          }
00220       } else {
00221          throw new PtrException("Error: trying to detach a NULL pointer in rc_ptrs.h");
00222       }
00223    }
00224 
00225 protected:
00226    void release()
00227    {
00228       if (ptr)
00229          ptr->unref();
00230       //else
00231       // cerr << "crisse de grosse erreur\n";
00232       ptr = 0;
00233    }
00234 
00235    void acquire()
00236    {
00237       if (ptr)
00238          ptr->ref();
00239       //else
00240       // cerr << "crisse de vraiment grosse erreur\n";
00241    }
00242 
00243 #ifndef BROKEN_TEMPLATES
00244    template <class Z>
00245    friend class RCPtr;
00246 #endif
00247 };
00248 
00249 class Object;
00254 typedef RCPtr<Object> ObjectRef;
00255 
00256 extern ObjectRef nilObject;
00257 
00258 #include "conversion.h"
00259 template <class X>
00260 template <class Z>
00261 RCPtr<X>& RCPtr<X>::operator= (const RCPtr<Z> &r)
00262 {
00263    if ((int) this != (int) (&r))
00264    {
00265       X *tmp=dynamic_cast<X*> (r.ptr);
00266       //if (!tmp) throw "RCPtr<X>: Illegal pointer conversion in operator =";
00267       if (!tmp) {
00268 
00269         //calling conversion code
00270         RCPtr<Object> conv = Conversion::convertTo<X>(r);
00271 
00272         tmp = dynamic_cast<X*>(conv.ptr);
00273 
00274         if (!tmp) {
00275           throw new GeneralException("Something is wrong in RCPtr::operator=, this should not happen.",__FILE__,__LINE__);
00276         }
00277         //must do that, since conv is local and we don't want the object to be deleted!
00278         release();
00279         ptr=tmp;
00280         acquire();
00281       } else {
00282         release();
00283         ptr=tmp;
00284         acquire();
00285       }
00286    }
00287    return *this;
00288 }
00289 
00290 template <class X>
00291 template <class Z>
00292 RCPtr<X>::RCPtr (const RCPtr<Z> &r)
00293 {
00294   X *tmp=dynamic_cast<X*> (r.ptr);
00295   //if (!tmp) throw "RCPtr<X>: Illegal pointer conversion in operator =";
00296   if (!tmp) {
00297     
00298     //calling conversion code
00299     RCPtr<Object> conv = Conversion::convertTo<X>(r);
00300     tmp = dynamic_cast<X*>(conv.ptr);
00301     
00302     if (!tmp) {
00303       throw new GeneralException("Something is wrong in RCPtr::operator=, this should not happen.",__FILE__,__LINE__);
00304     }
00305     //must do that, since conv is local and we don't want the object to be deleted!
00306     ptr=tmp;
00307     acquire();
00308   } else {
00309     ptr=tmp;
00310     acquire();
00311   }
00312 }
00313 
00314 }//end namespace FD
00315 
00316 #endif
00317 

Generated on Wed Oct 5 14:28:56 2005 for FlowDesigner by  doxygen 1.4.4