Main Page | Namespace List | Class Hierarchy | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages

DynObj.hh

Go to the documentation of this file.
00001 #ifndef NO_PTR_DYNOBJ_H
00002 #define NO_PTR_DYNOBJ_H
00003 
00023 #include "nullness.hh"  // use
00024 #include "DynObjKey.hh" // use
00025 #include "RRefUsage.hh" // contain
00026 #include "Deleter.hh"   // inherit
00027 #include "Contexts.hh"  // inherit
00028 #include "NoPtrFwd.hh"  // use
00029 
00030 /* Define specializations of std::swap, and declare auto_ptr
00031    so don't need to include its full header. Note that defining 
00032    specializations in the std namespace is considered appropriate
00033    (what's not is to \em add new members to the namespace).
00034    */
00035 namespace std
00036 {
00037     // forward declare auto_ptr so we don't have to include 
00038     // the whole <memory> file; user will be including it anyways.
00039     template<typename TT> class auto_ptr;
00040     
00041     // disregard current Standard: define swap for simple DynObj
00042     template <typename ObjType>
00043     inline void 
00044     swap(NoPtr::DynObj<ObjType>& lhs, 
00045          NoPtr::DynObj<ObjType>& rhs)
00046     {
00047         lhs.swap(rhs);
00048     }
00049         
00050     // disregard current Standard: define swap for value DynObj
00051     template <typename ObjType>
00052     inline void 
00053     swap(NoPtr::DynObj<ObjType, NoPtr::InValueContainer>& lhs, 
00054          NoPtr::DynObj<ObjType, NoPtr::InValueContainer>& rhs)
00055     {
00056         lhs.swap(rhs);
00057     }
00058         
00059     // disregard current Standard: define swap for other value DynObj
00060     template <typename ObjType>
00061     inline void 
00062     swap(NoPtr::DynObj<ObjType, NoPtr::InValueContainerOpt1>& lhs, 
00063          NoPtr::DynObj<ObjType, NoPtr::InValueContainerOpt1>& rhs)
00064     {
00065         lhs.swap(rhs);
00066     }
00067         
00068     // disregard current Standard: define swap for other value DynObj
00069     template <typename ObjType>
00070     inline void 
00071     swap(NoPtr::DynObj<ObjType, NoPtr::InValueContainerOpt2>& lhs, 
00072          NoPtr::DynObj<ObjType, NoPtr::InValueContainerOpt2>& rhs)
00073     {
00074         lhs.swap(rhs);
00075     }
00076         
00077     /* \todo Specialize iter_swap for DynObj: 
00078     template<typename ForwardIter1, typename ForwardIter2>
00079     inline void
00080     iter_swap(ForwardIter1 fi1, ForwardIter2 fi2)
00081     {
00082         fi1->swap(*fi2);
00083     }*/
00084 
00085 }
00086 
00087 namespace NoPtr
00088 {
00090     template <typename TT, class Context>
00091     inline bool 
00092     isNull(const DynObj<TT,Context>& p) {return p.isNull();}
00093 
00096     template <typename TT, class Context>
00097     inline bool 
00098     isNotNull(const DynObj<TT,Context>& p) {return p.isNotNull();}
00099 
00100     template <typename ObjType, class Context>
00101     class DynObj // inherit so EBO (empty base optimization) possible
00102                  // and privately since not for polymorphism 
00103         : private NoPtrImpl::Deleter<ObjType>, 
00104           private Context
00105     {
00106         private:
00108             template <typename, class> friend class DynObj;
00110             template <typename> friend class DynTmp;
00111             
00112         public:
00114             typedef ObjType ObjectType;
00116             typedef DynObj<ObjType,NoPtr::InValueContainer> 
00117                     InValueContainer;
00119             typedef DynObj<ObjType,NoPtr::InValueContainerOpt1> 
00120                     InValueContainerOpt1;
00122             typedef DynObj<ObjType,NoPtr::InValueContainerOpt2> 
00123                     InValueContainerOpt2;
00124 
00125         public:
00127 
00128             DynObj() throw(): _obj(NullPtr) {}
00130             explicit DynObj(ObjType* ptr) throw(): _obj(ptr) {}
00131             
00133             template <typename ObjType2>
00134             explicit DynObj(std::auto_ptr<ObjType2>& aptr) throw()
00135                 : _obj( aptr.release() ) {}
00137             template <typename ObjType2>
00138             DynObj(const DynTmp<ObjType2>& mobj) throw()
00139             { 
00140                 mobj.deliver( _obj, _rrefUsage, 
00141                               NoPtrImpl::DynObjKey<ObjType>() );
00142             }
00143             
00145            ~DynObj()
00146             {
00147                 if (soleOwner()) 
00148                 {
00149                     destroy(_obj);
00150                     _rrefUsage.destroy();
00151                 }
00152             }
00154             
00155             // If TEST_ALL_INSTANTIATE is defined we can't define copy 
00156             // since it is prevented by default via a compilation error
00157             #ifndef TEST_ALL_INSTANTIATE
00158             /*  Copy a dynobj. This is only provided for use by 
00159                 copyable contexts such as STL containers. I.e. it compiles 
00160                 only if the second template parameter is InValueContainer 
00161                 (or InValueContainerOpt*). You should never have to use this 
00162                 yourself. */
00163             DynObj(const DynObj& rhs) // only for non-default context
00164                 : NoPtrImpl::Deleter<ObjType>(), Context(rhs), _obj(rhs._obj),
00165                   _rrefUsage(rhs._rrefUsage) 
00166             {
00167                 Context::checkCopyable();
00168                 // do NOT do rhs._obj = NullPtr;
00169                 // since when copyable rhs is const
00170             }
00171             #endif
00172             
00174             
00176             void acquire(ObjType* ptr) 
00177             {
00178                 assert(ptr != _obj); // would mean bug!
00179                 assert(soleOwner());
00180                 destroy(_obj); // MUST NOT throw
00181                 _rrefUsage.reset();
00182                 _obj = ptr;
00183             }
00185             template <typename ObjType2>
00186             void acquire(std::auto_ptr<ObjType2>& aptr)
00187             {
00188                 acquire(aptr.release());
00189             }
00190 
00196             template <typename ObjType2, class Context2>
00197             void acquire(DynObj<ObjType2,Context2>& rhs)
00198             {
00199                 assert(rhs._obj != _obj); // would mean bug!
00200                 assert(soleOwner());
00201                 destroy(_obj); // MUST NOT throw
00202                 _rrefUsage.reset();
00203                 
00204                 assert(rhs.soleOwner());
00205                 _obj = rhs._obj;
00206                 rhs._obj = NullPtr; 
00207                 rhs._rrefUsage.moveTo(_rrefUsage);
00208                 // leave rhs._obj in registry
00209             }
00213             template <typename ObjType2>
00214             void acquire(const DynTmp<ObjType2>& mobj)
00215             {
00216                 assert(soleOwner()); 
00217                 reset();
00218                 mobj.deliver( _obj, _rrefUsage, 
00219                               NoPtrImpl::DynObjKey<ObjType>() );
00220             }
00222             
00224             
00227             void reset() 
00228             {
00229                 assert(soleOwner());
00230                 destroy(_obj); // MUST NOT throw
00231                 _rrefUsage.reset();
00232                 _obj = NullPtr;
00233             }
00234             
00236             void swap(DynObj& rhs) throw() 
00237             {
00238                 std::swap(_obj, rhs._obj);
00239                 _rrefUsage.swap(rhs._rrefUsage);
00240                 Context::swap(rhs);
00241             }
00242                 
00247             ObjType* release() throw()
00248             {
00249                 assert(soleOwner()); 
00250                 _rrefUsage.reset();
00251                 ObjType* const tmp = _obj;
00252                 _obj = NullPtr;
00253                 return tmp;
00254             }
00255 
00260             DynTmp<ObjType> moveToTmp() throw()
00261             {
00262                 assert(soleOwner()); 
00263                 ObjType* const tmp = _obj;
00264                 _obj = NullPtr;
00265                 return DynTmp<ObjType>( tmp, _rrefUsage, 
00266                                         NoPtrImpl::DynObjKey<ObjType>() );
00267             }
00275             DynTmp<ObjType> giveAway() throw() {return moveToTmp();}
00276             
00277             
00279             
00281             
00283             bool isNull() const throw() 
00284             {
00285                 assert(soleOwner()); 
00286                 return _obj == NullPtr;
00287             }
00289             bool isNotNull() const throw() 
00290             {
00291                 assert(soleOwner()); 
00292                 return _obj != NullPtr;
00293             }
00294             
00299             ObjType* getPtr() const throw() 
00300             { 
00301                 assert(soleOwner()); 
00302                 return _obj; 
00303             }
00304             
00306             
00308             
00317             ObjType& operator()() const
00318             {
00319                 return *(operator->());
00320             }
00321             
00334             ObjType& operator*() const
00335             {
00336                 return *(operator->());
00337             }
00338             
00340             template <typename ObjType2>
00341             void operator=(const DynTmp<ObjType2>& mobj)
00342             {
00343                 acquire(mobj);
00344             }                
00361             template <typename ObjType2, class Context2>
00362             bool operator<(const DynObj<ObjType2,Context2>& rhs) const throw()
00363             {
00364                 if (_obj && rhs._obj) // both non-null:
00365                     return (*_obj) < *(rhs._obj);
00366                 
00367                 // at least one null, compare pointers
00368                 if (_obj == NullPtr) return true;
00369                 // else rhs must be null, so result is false:
00370                 assert(rhs._obj == NullPtr);
00371                 return false;
00372             }
00376             template <typename ObjType2, class Context2>
00377             bool operator==(const DynObj<ObjType2,Context2>& rhs) const throw()
00378             {
00379                 if (_obj && rhs._obj) // compare DAO's
00380                     return (_obj == rhs._obj) || ((*_obj) == *(rhs._obj));
00381                 
00382                 // at least one is null, so compare pointers
00383                 return _obj == rhs._obj;
00384             }
00386             template <typename ObjType2, class Context2>
00387             bool operator!=(const DynObj<ObjType2,Context2>& rhs) const throw()
00388             {
00389                 return !(*this == rhs);
00390             }
00391             
00392             #include "opConstWarningOff.hpp"
00401             operator const DynObj<const ObjType,Context>&() const throw()
00402             {
00403                 typedef DynObj<const ObjType,Context> DynConstObj;
00404                 return * static_cast<const DynConstObj*>(
00405                      static_cast<const void*>(this)
00406                 );
00407             }
00408             #include "opConstWarningOn.hpp"
00410             
00411             // If TEST_ALL_INSTANTIATE is defined we can't define assignment
00412             // since it is prevented by default via a compilation error
00413             #ifndef TEST_ALL_INSTANTIATE
00414             
00415             /*  Copy from a dynobj. This is only provided for use by 
00416                 value-based containers such as STL containers. It compiles 
00417                 only if the second template parameter is InValueContainer 
00418                 (or InValueContainerOpt*). You should never have to use this 
00419                 yourself. 
00420                 
00421                 \todo Test this rigorously since complex function; especially
00422                       if _rrefusage has or hasn't been initialized
00423                 */
00424             DynObj& operator=(const DynObj& rhs)
00425             {
00426                 // we know that if _obj == rhs._obj then *this is 
00427                 // either rhs or both are null, then no need to copy
00428                 if (_obj == rhs._obj) return *this;
00429                 
00430                 // ok, valid copy:
00431                 
00432                 Context::checkCopyable(); // compile time check
00433                 if (soleOwner()) 
00434                 // only one owning _obj so destroy it; otherwise, 
00435                 // one of other owners will do it;
00436                 {
00437                     destroy(_obj);
00438                     _rrefUsage.reset();
00439                 }
00440                 
00441                 _obj = rhs._obj;
00442                 // do NOT do rhs._obj = NullPtr;
00443                 // since when copyable rhs is const
00444                 _rrefUsage = rhs._rrefUsage;
00445                 Context::operator=(rhs);
00446                 return *this;
00447             }
00448             #endif // TEST_ALL_INSTANTIATE
00449                 
00450         public: // only to RRef
00451                 
00452             /* Public just to avoid more friends. From user point of view,
00453                this method is private, i.e. don't use it. This is how DynObj 
00454                allows RRef to get data that will allow RRef to know when 
00455                DynObj has destroyed DAO. 
00456                */
00457             void getRRefUsage(NoPtrImpl::RRefUsageForUser& rrefUsage) const
00458             {
00459                 _rrefUsage.create();
00460                 rrefUsage.shareFrom(_rrefUsage);
00461             }
00462             
00463         private:
00464             /*  The traditional indirection operator to access members
00465                 of the ObjType instance referred to by this RRef. E.g.
00466                 use it as dynobj->method() to access Foo::method() for 
00467                 a dynobj of type DynObj<Foo>.
00468                 */
00469             ObjType* operator->() const
00470             {
00471                 assert(soleOwner()); 
00472                 assert(NoPtr::isNotNull(_obj));
00473                 return _obj;
00474             }
00475             
00476         private:
00477             ObjType* _obj; 
00478             mutable NoPtrImpl::RRefUsageForOwner _rrefUsage; 
00479     };
00480                 
00481 } // namespace
00482 
00603 #endif // NO_PTR_DYNOBJ_H    

Generated on Mon Aug 4 18:51:23 2003 for NoPtr C++ Library by doxygen 1.3.2