Teuchos_RefCountPtr.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_REFCOUNTPTR_H
00030 #define TEUCHOS_REFCOUNTPTR_H
00031 
00039 #include "Teuchos_RefCountPtrDecl.hpp"
00040 #include "Teuchos_TestForException.hpp"
00041 #include "Teuchos_dyn_cast.hpp"
00042 #include "Teuchos_map.hpp"
00043 
00044 // /////////////////////////////////////////////////////////////////////////
00045 // Inline implementations below, not for the client to look at.
00046 
00047 namespace Teuchos {
00048 
00049 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00050 
00051 namespace PrivateUtilityPack {
00052 
00053 // Assert that the pointer is not null
00054 void throw_null( const std::string &type_name );
00055 
00056 // Node class to keep track of the delete address and
00057 // the reference count for RefCountPtr<...>
00058 class RefCountPtr_node {
00059 public:
00060   RefCountPtr_node(bool has_ownership)
00061     : count_(1), has_ownership_(has_ownership), extra_data_map_(NULL)
00062   {}
00063   virtual ~RefCountPtr_node()
00064   {
00065     if(extra_data_map_) delete extra_data_map_;
00066   }
00067   int count() const {
00068     return count_;  
00069   }
00070   int incr_count() {
00071     return ++count_;
00072   }
00073   int deincr_count() {
00074     return --count_;
00075   }
00076   void has_ownership(bool has_ownership) {
00077     has_ownership_ = has_ownership;
00078   }
00079   bool has_ownership() const {
00080     return has_ownership_;
00081   }
00082   void set_extra_data( const any &extra_data, const std::string& name, bool force_unique, EPrePostDestruction destroy_when );
00083   any& get_extra_data( const std::string& type_name, const std::string& name );
00084   const any& get_extra_data( const std::string& type_name, const std::string& name ) const {
00085     return const_cast<RefCountPtr_node*>(this)->get_extra_data(type_name,name);
00086   }
00087 protected:
00088   void pre_delete_extra_data() {
00089     if(extra_data_map_) impl_pre_delete_extra_data();
00090   }
00091 private:
00092   struct extra_data_entry_t {
00093     extra_data_entry_t() : destroy_when(POST_DESTROY) {}
00094     extra_data_entry_t( const any &_extra_data, EPrePostDestruction _destroy_when )
00095       : extra_data(_extra_data), destroy_when(_destroy_when) {}
00096     any extra_data;
00097     EPrePostDestruction destroy_when;
00098   };  
00099   typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
00100   int                 count_;
00101   bool                has_ownership_;
00102   extra_data_map_t    *extra_data_map_;
00103   // Above is made a pointer to reduce overhead for the general case
00104   // where this is not used
00105   void impl_pre_delete_extra_data();
00106   // Not defined and not to be called
00107   RefCountPtr_node();
00108   RefCountPtr_node(const RefCountPtr_node&);
00109   RefCountPtr_node& operator=(const RefCountPtr_node&);
00110 };  // end class RefCountPtr_node;
00111 
00112 // Implementation class for actually deleting the object if has_ownership() == true.
00113 template<class T, class Dealloc_T>
00114 class RefCountPtr_node_tmpl : public RefCountPtr_node {
00115 public:
00116 
00117   //
00118   RefCountPtr_node_tmpl(T* p, Dealloc_T dealloc, bool has_ownership)
00119     : RefCountPtr_node(has_ownership), ptr_(p), dealloc_(dealloc)
00120   {}
00121   //
00122   Dealloc_T& get_dealloc() { return dealloc_; }
00123   //
00124   const Dealloc_T& get_dealloc() const { return dealloc_; }
00125   //
00126   ~RefCountPtr_node_tmpl() {
00127     this->pre_delete_extra_data();
00128     if( has_ownership() )
00129       dealloc_.free(ptr_);
00130   }
00131 
00132 private:
00133 
00134   T           *ptr_;
00135   Dealloc_T   dealloc_;
00136   // not defined and not to be called
00137   RefCountPtr_node_tmpl();
00138   RefCountPtr_node_tmpl(const RefCountPtr_node_tmpl&);
00139   RefCountPtr_node_tmpl& operator=(const RefCountPtr_node_tmpl&);
00140 
00141 }; // end class RefCountPtr_node_tmpl<T>
00142 
00143 } // end namespace PrivateUtilityPack 
00144 
00145 #endif
00146 
00147 // /////////////////////////////////////////////////////////////////////////////////
00148 // Inline member functions for RefCountPtr<...>.
00149 
00150 template<class T>
00151 inline
00152 RefCountPtr<T>::RefCountPtr( ENull )
00153   : ptr_(NULL)
00154   , node_(NULL)
00155 {}
00156 
00157 template<class T>
00158 REFCOUNTPTR_INLINE
00159 RefCountPtr<T>::RefCountPtr(const RefCountPtr<T>& r_ptr)
00160   : ptr_(r_ptr.ptr_), node_(r_ptr.node_)
00161 {
00162   if(node_) node_->incr_count();
00163 }
00164 
00165 template<class T>
00166 REFCOUNTPTR_INLINE
00167 template <class T2>
00168 RefCountPtr<T>::RefCountPtr(const RefCountPtr<T2>& r_ptr)
00169   : ptr_(const_cast<T2*>(r_ptr.get()))                 // will not compile if T1 is not an ancestor of T2
00170   , node_(const_cast<node_t*>(r_ptr.access_node()))
00171 {
00172   if(node_) node_->incr_count();
00173 }
00174 
00175 template<class T>
00176 REFCOUNTPTR_INLINE
00177 RefCountPtr<T>::~RefCountPtr()
00178 {
00179   if(node_ && node_->deincr_count() == 0 ) delete node_;
00180 }
00181 
00182 template<class T>
00183 REFCOUNTPTR_INLINE
00184 RefCountPtr<T>& RefCountPtr<T>::operator=(const RefCountPtr<T>& r_ptr) {
00185   if(node_) {
00186     if( r_ptr.node_ == node_ )
00187       return *this; // Assignment to self!
00188     if( !node_->deincr_count() ) {
00189       delete node_;
00190     }
00191   }
00192   ptr_  = r_ptr.ptr_;
00193   node_ = r_ptr.node_;
00194   if(node_) node_->incr_count();
00195   return *this;
00196 }
00197 
00198 template<class T>
00199 inline
00200 T* RefCountPtr<T>::operator->() const {
00201 #ifdef _DEBUG
00202   assert_not_null();
00203 #endif
00204   return ptr_;
00205 }
00206 
00207 template<class T>
00208 inline
00209 T& RefCountPtr<T>::operator*() const {
00210 #ifdef _DEBUG
00211   assert_not_null();
00212 #endif
00213   return *ptr_;
00214 }
00215 
00216 template<class T>
00217 inline
00218 T* RefCountPtr<T>::get() const {
00219   return ptr_;
00220 }
00221 
00222 template<class T>
00223 REFCOUNTPTR_INLINE
00224 T* RefCountPtr<T>::release() {
00225   if(node_)
00226     node_->has_ownership(false);
00227   return ptr_;
00228 }
00229 
00230 template<class T>
00231 REFCOUNTPTR_INLINE
00232 int RefCountPtr<T>::count() const {
00233   if(node_)
00234     return node_->count();
00235   return 0;
00236 }
00237 
00238 template<class T>
00239 REFCOUNTPTR_INLINE
00240 void RefCountPtr<T>::set_has_ownership() {
00241   if(node_)
00242     node_->has_ownership(true);
00243 }
00244 
00245 template<class T>
00246 REFCOUNTPTR_INLINE
00247 bool RefCountPtr<T>::has_ownership() const {
00248   if(node_)
00249     return node_->has_ownership();
00250   return false;
00251 }
00252 
00253 template<class T>
00254 REFCOUNTPTR_INLINE
00255 bool RefCountPtr<T>::shares_resource(const RefCountPtr<T>& r_ptr) const {
00256   return node_ == r_ptr.node_;
00257 }
00258 
00259 template<class T>
00260 inline
00261 const RefCountPtr<T>& RefCountPtr<T>::assert_not_null() const {
00262   if(!ptr_) PrivateUtilityPack::throw_null(typeid(T).name());
00263   return *this;
00264 }
00265 
00266 // very bad public functions
00267 
00268 template<class T>
00269 inline
00270 RefCountPtr<T>::RefCountPtr( T* p, bool has_ownership )
00271   : ptr_(p)
00272   , node_( p ? new PrivateUtilityPack::RefCountPtr_node_tmpl<T,DeallocDelete<T> >(p,DeallocDelete<T>(),has_ownership) : NULL )
00273 {}
00274 
00275 template<class T>
00276 REFCOUNTPTR_INLINE
00277 template<class Dealloc_T>
00278 RefCountPtr<T>::RefCountPtr( T* p, Dealloc_T dealloc, bool has_ownership )
00279   : ptr_(p)
00280   , node_( p ? new PrivateUtilityPack::RefCountPtr_node_tmpl<T,Dealloc_T>(p,dealloc,has_ownership) : NULL )
00281 {}
00282 
00283 template<class T>
00284 inline
00285 RefCountPtr<T>::RefCountPtr( T* p, node_t* node)
00286   : ptr_(p), node_(node)
00287 {
00288   if(node_) node_->incr_count();
00289 }
00290 
00291 template<class T>
00292 inline
00293 T*& RefCountPtr<T>::access_ptr()
00294 { return ptr_; }
00295 
00296 template<class T>
00297 inline
00298 typename RefCountPtr<T>::node_t*& RefCountPtr<T>::access_node()
00299 { return node_; }
00300 
00301 template<class T>
00302 inline
00303 typename RefCountPtr<T>::node_t* RefCountPtr<T>::access_node() const
00304 { return node_; }
00305 
00306 } // end namespace Teuchos
00307 
00308 // /////////////////////////////////////////////////////////////////////////////////
00309 // Inline member functions for conversions for RefCountPtr<...>.
00310 
00311 template<class T>
00312 inline
00313 Teuchos::RefCountPtr<T>
00314 Teuchos::rcp( T* p, bool owns_mem )
00315 {
00316   return RefCountPtr<T>(p,owns_mem);
00317 }
00318 
00319 template<class T, class Dealloc_T>
00320 inline
00321 Teuchos::RefCountPtr<T>
00322 Teuchos::rcp( T* p, Dealloc_T dealloc, bool owns_mem )
00323 {
00324   return RefCountPtr<T>(p,dealloc,owns_mem);
00325 }
00326 
00327 template<class T2, class T1>
00328 REFCOUNTPTR_INLINE
00329 Teuchos::RefCountPtr<T2>
00330 Teuchos::rcp_implicit_cast(const RefCountPtr<T1>& p1)
00331 {
00332   T2 *check = p1.get(); // Make the compiler check if the conversion is legal
00333   RefCountPtr<T2> p2;
00334   if(p1.access_node()) {
00335     p2.access_ptr()  = check;
00336     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00337     p2.access_node()->incr_count();
00338   }
00339   return p2;
00340 }
00341 
00342 template<class T2, class T1>
00343 REFCOUNTPTR_INLINE
00344 Teuchos::RefCountPtr<T2>
00345 Teuchos::rcp_static_cast(const RefCountPtr<T1>& p1)
00346 {
00347   T2 *check = static_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00348   RefCountPtr<T2> p2;
00349   if(p1.access_node()) {
00350     p2.access_ptr()  = check;
00351     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00352     p2.access_node()->incr_count();
00353   }
00354   return p2;
00355 }
00356 
00357 template<class T2, class T1>
00358 REFCOUNTPTR_INLINE
00359 Teuchos::RefCountPtr<T2>
00360 Teuchos::rcp_const_cast(const RefCountPtr<T1>& p1)
00361 {
00362   T2 *check = const_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00363   RefCountPtr<T2> p2;
00364   if(p1.access_node()) {
00365     p2.access_ptr()  = check;
00366     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00367     p2.access_node()->incr_count();
00368   }
00369   return p2;
00370 }
00371 
00372 template<class T2, class T1>
00373 REFCOUNTPTR_INLINE
00374 Teuchos::RefCountPtr<T2>
00375 Teuchos::rcp_dynamic_cast(const RefCountPtr<T1>& p1, bool throw_on_fail)
00376 {
00377   RefCountPtr<T2> p2; // NULL by default
00378   if( p1.get() ) {
00379     T2 *check = NULL;
00380     if(throw_on_fail)
00381       check = &dyn_cast<T2>(*p1);
00382     else
00383       check = dynamic_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00384     if(check) {
00385       p2.access_ptr()  = check;
00386       p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00387       p2.access_node()->incr_count();
00388     }
00389   }
00390   return p2;
00391 }
00392 
00393 template<class T1, class T2>
00394 REFCOUNTPTR_INLINE
00395 void Teuchos::set_extra_data( const T1 &extra_data, const std::string& name, Teuchos::RefCountPtr<T2> *p, bool force_unique, EPrePostDestruction destroy_when )
00396 {
00397   *(*p); // Assert not NULL
00398   p->access_node()->set_extra_data( extra_data, name, force_unique, destroy_when );
00399 }
00400 
00401 template<class T1, class T2>
00402 REFCOUNTPTR_INLINE
00403 T1& Teuchos::get_extra_data( RefCountPtr<T2>& p, const std::string& name )
00404 {
00405   *p; // Assert not NULL
00406   return any_cast<T1>(p.access_node()->get_extra_data(typeid(T1).name(),name));
00407 }
00408 
00409 template<class T1, class T2>
00410 REFCOUNTPTR_INLINE
00411 const T1& Teuchos::get_extra_data( const RefCountPtr<T2>& p, const std::string& name )
00412 {
00413   *p; // Assert not NULL
00414   return any_cast<T1>(p.access_node()->get_extra_data(typeid(T1).name(),name));
00415 }
00416 
00417 template<class Dealloc_T, class T>
00418 REFCOUNTPTR_INLINE
00419 Dealloc_T&
00420 Teuchos::get_dealloc( RefCountPtr<T>& p )
00421 {
00422   *p; // Assert not NULL
00423   PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00424     *dnode = dynamic_cast<PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(p.access_node());
00425   TEST_FOR_EXCEPTION(
00426     dnode==NULL, std::logic_error
00427     ,"get_dealloc<" << typeid(Dealloc_T).name() << "," << typeid(T).name() << ">(p): "
00428     << "Error, requested type \'" << typeid(PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>).name()
00429     << "\' does not match actual type of the node \'" << typeid(*p.access_node()).name() << "!"
00430     );
00431   return dnode->get_dealloc();
00432 }
00433 
00434 template<class Dealloc_T, class T>
00435 inline
00436 const Dealloc_T& 
00437 Teuchos::get_dealloc( const Teuchos::RefCountPtr<T>& p )
00438 {
00439   return get_dealloc<Dealloc_T>(const_cast<RefCountPtr<T>&>(p));
00440 }
00441 
00442 #endif  // REFCOUNTPTR_H

Generated on Thu Sep 18 12:41:17 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1