00001
00020 #ifndef MANGO_OWNED_PTR_H
00021 #define MANGO_OWNED_PTR_H
00022
00023 #include <memory>
00024 #include <stdexcept>
00025
00026 #include "nullness.hh"
00027 #include "ObjSharing.hh"
00028 #include "ValidityChecker.hh"
00029 #include "CheckedPtr.hh"
00030 #include "Ownership.hh"
00031 #include "BLinkableFWD.hh"
00032 #include "BLinkFWD.hh"
00033 #include "OwnedFWD.hh"
00034
00035 namespace MangoPtr
00036 {
00037
00038 template <typename T, OwnershipType oshiptype>
00039 inline bool
00040 isNull(const Owned<T,oshiptype>& p) {return p.isNull();}
00041
00042
00043 template <typename T, OwnershipType oshiptype>
00044 inline bool
00045 isNotNull(const Owned<T,oshiptype>& p) {return p.isNotNull();}
00046
00047 template <typename OType, OwnershipType oshiptype>
00048 class Owned<OType*, oshiptype>
00049 : protected BLinkable<ForOwnedBy::Wrapper>
00050 {
00051 protected:
00053 typedef OType* PType;
00055 template <typename O2Type, OwnershipType oshiptype2>
00056 friend class Owned;
00057
00058 public:
00060 typedef OType ObjectType;
00061
00063
00064
00065 Owned(): optr(NullPtr), deleteObj(&Owned::callDelete) {}
00066
00067
00068 #ifndef MANGO_ALL_TEMPLATE_INSTANTIATE
00069 inline Owned(const Owned&);
00070 template <typename O2Type> inline
00071 Owned(const Owned<O2Type, oshiptype>&);
00072 #endif
00073 explicit Owned(OType*);
00074 template <typename O2Type> explicit inline
00075 Owned(std::auto_ptr<O2Type>&);
00076 template <typename O2Type> explicit inline
00077 Owned(Ownership<O2Type, oshiptype>);
00079 inline ~Owned();
00080
00081 public:
00083
00084 inline void swap(Owned& rhs);
00085 inline PType release();
00087 inline void reset() {resetToDefault(); nullify(optr);}
00088 inline Ownership<PType, oshiptype> giveOwnership();
00089
00090
00091 #ifndef MANGO_ALL_TEMPLATE_INSTANTIATE
00094 inline Owned& operator=(const Owned& rhs) {return assignFrom(rhs);}
00097 template <typename O2Type>
00098 inline Owned&
00099 operator=(const Owned<O2Type, oshiptype>& rhs) {return assignFrom(rhs);}
00100 #endif
00101
00102 inline void takeOwnership(OType* p);
00103 template <typename O2Type> inline void
00104 takeOwnership(std::auto_ptr<O2Type>&);
00105 template <typename O2Type> inline void
00106 takeOwnership(Ownership<O2Type, oshiptype>);
00108
00109 public:
00111
00112 inline PType cloneObjNew() const;
00113 inline PType shareUsage(ValidityChecker&) const;
00114 #include "opConstWarningOff.pp"
00115 inline operator const Owned<const OType*, oshiptype>&() const;
00116 #include "opConstWarningOn.pp"
00118
00119 public:
00120
00121
00123
00126 inline bool isNull() const { return ! isNotNull(); }
00128 size_t getCountUser() const {return sharing.getCountUser();}
00130 size_t getCountOwned() const {return sharing.getCountOwned();}
00132 bool owns(PType rhs) const {return MangoPtr::isNotNull(rhs) && rhs==optr;}
00135 template <typename O2Type>
00136 bool owns(const BLink<O2Type>& rhs) const {return owns(rhs());}
00142 CheckedPtr<OType> operator()() const {return isNotNull() ? optr : NullPtr;}
00144 OType* ptr() const {return isNotNull() ? optr : NullPtr;}
00147 bool operator==(const Owned& rhs) const {return optr == rhs.optr;}
00149 bool operator!=(const Owned& rhs) const {return optr != rhs.optr;}
00151 bool operator<(const Owned& rhs) const {return optr < rhs.optr;}
00152
00153
00154 private:
00155 inline void resetToDefault();
00156 template <typename O2Type>
00157 inline Owned& assignFrom(const Owned<O2Type, oshiptype>&);
00159 inline void callDelete() {delete optr;}
00160
00161
00162 private:
00163 PType optr;
00164
00171 mutable ObjSharing<oshiptype> sharing;
00172
00173 typedef void (Owned::*DeleteFn)();
00174 const DeleteFn deleteObj;
00175 };
00176
00177 #ifndef MANGO_ALL_TEMPLATE_INSTANTIATE
00178
00179 template <typename OType, OwnershipType oshiptype>
00180 inline
00181 Owned<OType*, oshiptype>::Owned(const Owned& owner)
00182 : optr(owner()), sharing(owner.sharing((void*)optr)),
00183 deleteObj(&Owned::callDelete)
00184 {
00185 assert(MangoPtr::isNull(optr) == isNull());
00186 }
00187
00189 template <typename OType, OwnershipType oshiptype>
00190 template <typename O2Type>
00191 inline
00192 Owned<OType*, oshiptype>::Owned(const Owned<O2Type,oshiptype>& owner)
00193 : optr(owner()), sharing(owner.sharing((void*)optr)),
00194 deleteObj(&Owned::callDelete)
00195 {
00196 assert(MangoPtr::isNull(optr) == isNull());
00197 }
00198 #endif // MANGO_ALL_TEMPLATE_INSTANTIATE
00199
00201 template <typename OType, OwnershipType oshiptype>
00202 inline
00203 Owned<OType*, oshiptype>::Owned(OType* p)
00204 : optr(p), deleteObj(&Owned::callDelete)
00205
00206 {
00207 }
00208
00212 template <typename OType, OwnershipType oshiptype>
00213 template <typename O2Type>
00214 inline
00215 Owned<OType*, oshiptype>::Owned(std::auto_ptr<O2Type>& ap)
00216 : optr(ap.release()), deleteObj(&Owned::callDelete)
00217
00218 {
00219 }
00220
00225 template <typename OType, OwnershipType oshiptype>
00226 template <typename O2Type>
00227 inline
00228 Owned<OType*, oshiptype>::Owned(Ownership<O2Type, oshiptype> os)
00229 : optr(NullPtr), deleteObj(&Owned::callDelete)
00230 {
00231 sharing.swap(os.owner.sharing);
00232 optr = os.owner();
00233 os.owner.optr = NullPtr;
00234 assert(MangoPtr::isNull(optr) == isNull());
00235 assert(os.owner.isNull());
00236 }
00237
00239 template <typename OType, OwnershipType oshiptype>
00240 inline
00241 Owned<OType*, oshiptype>::~Owned()
00242 {
00243 if (sharing.destructNeedsDelete((void*)optr))
00244 {
00245 (this->*deleteObj)();
00247 sharing.invalidateUsage();
00248 }
00249 }
00250
00259 template <typename OType, OwnershipType oshiptype>
00260 inline void
00261 Owned<OType*, oshiptype>::resetToDefault()
00262 {
00263 if (sharing.destructNeedsDelete((void*)optr) )
00264 {
00265 (this->*deleteObj)();
00267 sharing.invalidateUsage();
00268 }
00269
00270 sharing.unlinkNew();
00271 }
00272
00277 template <typename OType, OwnershipType oshiptype>
00278 inline void
00279 Owned<OType*, oshiptype>::takeOwnership(OType* p)
00280 {
00281 resetToDefault();
00282 optr = p;
00283 }
00284
00289 template <typename OType, OwnershipType oshiptype>
00290 template <typename O2Type>
00291 inline void
00292 Owned<OType*, oshiptype>::takeOwnership(std::auto_ptr<O2Type>& ap)
00293 {
00294 resetToDefault();
00295 optr = ap.release();
00296 }
00297
00305 template <typename OType, OwnershipType oshiptype>
00306 template <typename O2Type>
00307 inline void
00308 Owned<OType*, oshiptype>::takeOwnership(Ownership<O2Type, oshiptype> os)
00309 {
00310 resetToDefault();
00311 sharing.swap(os.owner.sharing);
00312 optr = os.owner();
00313 nullify(os.owner.optr);
00314 assert(MangoPtr::isNull(optr) == isNull());
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 template <typename OType, OwnershipType oshiptype>
00324 template <typename O2Type>
00325 inline Owned<OType*, oshiptype>&
00326 Owned<OType*, oshiptype>::assignFrom(const Owned<O2Type, oshiptype>& rhs)
00327 {
00328 resetToDefault();
00329 optr = rhs();
00330 sharing = rhs.sharing((void*)optr);
00331 return *this;
00332 }
00333
00340 template <typename OType, OwnershipType oshiptype>
00341 inline Ownership<OType*, oshiptype>
00342 Owned<OType*, oshiptype>::giveOwnership()
00343 {
00344 return Ownership<OType*, oshiptype>(*this);
00345 }
00346
00348 template <typename OType, OwnershipType oshiptype>
00349 inline void
00350 Owned<OType*, oshiptype>::swap(Owned& rhs)
00351 {
00352 std::swap(optr, rhs.optr);
00353 sharing.swap(rhs.sharing);
00354 }
00355
00364 template <typename OType, OwnershipType oshiptype>
00365 inline OType*
00366 Owned<OType*, oshiptype>::cloneObjNew()
00367 const
00368 {
00369 return isNotNull() ? new OType(*optr) : NullPtr;
00370 }
00371
00389 template <typename OType, OwnershipType oshiptype>
00390 inline OType*
00391 Owned<OType*, oshiptype>::release()
00392 {
00393
00394 sharing.invalidateUsage();
00395
00396 sharing.unlinkNew();
00397 PType tmp = optr;
00398 nullify(optr);
00399 return tmp;
00400 }
00401
00414 template <typename OType, OwnershipType oshiptype>
00415 inline
00416 Owned<OType*, oshiptype>::operator const Owned<const OType*, oshiptype>&()
00417 const
00418 {
00419 return * static_cast<const Owned<const OType*, oshiptype>*>(
00420 static_cast<const void*>(this)
00421 );
00422 }
00423
00431 template <typename OType, OwnershipType oshiptype>
00432 inline OType*
00433 Owned<OType*, oshiptype>::shareUsage(ValidityChecker& val)
00434 const
00435 {
00436 val = sharing((void*)optr).usage();
00437 assert(val.isShared());
00438 assert(val.isValid() == MangoPtr::isNotNull(*this));
00439 return (*this)();
00440 }
00441
00442 }
00443
00535 #endif // MANGO_OWNED_PTR_H