00001
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
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
00105
00106
00107 public:
00108 explicit RCPtr(X* p=0) : ptr(p)
00109 {
00110
00111 }
00112
00113 bool isNil() {return ptr == 0;}
00114
00115 template <class Z>
00116 RCPtr(const RCPtr<Z> &r);
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 RCPtr(const RCPtr<X> &r)
00131 {
00132 ptr=r.ptr;
00133
00134 acquire();
00135 }
00136
00137 ~RCPtr() { release(); }
00138
00139
00140 template <class Z>
00141 RCPtr& operator= (const RCPtr<Z> &r)
00142 ;
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 RCPtr& operator= (const RCPtr<X> &r)
00157 {
00158 if (this != &r)
00159 {
00160 release();
00161 ptr = r.ptr;
00162
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
00175 if (!tmp) throw new PtrCastException<Z,X>(r);
00176 release();
00177 ptr=tmp;
00178
00179 }
00180 return *this;
00181 }
00182
00183 RCPtr& operator= (X *r)
00184 {
00185 if (ptr != r)
00186 {
00187 release();
00188 ptr = r;
00189
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
00231
00232 ptr = 0;
00233 }
00234
00235 void acquire()
00236 {
00237 if (ptr)
00238 ptr->ref();
00239
00240
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
00267 if (!tmp) {
00268
00269
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
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
00296 if (!tmp) {
00297
00298
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
00306 ptr=tmp;
00307 acquire();
00308 } else {
00309 ptr=tmp;
00310 acquire();
00311 }
00312 }
00313
00314 }
00315
00316 #endif
00317