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_HPP
00030 #define TEUCHOS_REFCOUNTPTR_HPP
00031 
00042 #include "Teuchos_RefCountPtrDecl.hpp"
00043 #include "Teuchos_TestForException.hpp"
00044 #include "Teuchos_dyn_cast.hpp"
00045 #include "Teuchos_map.hpp"
00046 
00047 // /////////////////////////////////////////////////////////////////////////
00048 // Inline implementations below, not for the client to look at.
00049 
00050 namespace Teuchos {
00051 
00052 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00053 
00054 namespace PrivateUtilityPack {
00055 
00056 // Assert that the pointer is not null
00057 void throw_null( const std::string &type_name );
00058 
00059 // Node class to keep track of the delete address and
00060 // the reference count for RefCountPtr<...>
00061 class RefCountPtr_node {
00062 public:
00063   RefCountPtr_node(bool has_ownership)
00064     : count_(1), has_ownership_(has_ownership), extra_data_map_(NULL)
00065   {}
00066   virtual ~RefCountPtr_node()
00067   {
00068     if(extra_data_map_) delete extra_data_map_;
00069   }
00070   int count() const {
00071     return count_;  
00072   }
00073   int incr_count() {
00074     return ++count_;
00075   }
00076   int deincr_count() {
00077     return --count_;
00078   }
00079   void has_ownership(bool has_ownership) {
00080     has_ownership_ = has_ownership;
00081   }
00082   bool has_ownership() const {
00083     return has_ownership_;
00084   }
00085   void set_extra_data( const any &extra_data, const std::string& name, bool force_unique, EPrePostDestruction destroy_when );
00086   any& get_extra_data( const std::string& type_name, const std::string& name );
00087   const any& get_extra_data( const std::string& type_name, const std::string& name ) const {
00088     return const_cast<RefCountPtr_node*>(this)->get_extra_data(type_name,name);
00089   }
00090   any* get_optional_extra_data( const std::string& type_name, const std::string& name );
00091   const any* get_optional_extra_data( const std::string& type_name, const std::string& name ) const {
00092     return const_cast<RefCountPtr_node*>(this)->get_optional_extra_data(type_name,name);
00093   }
00094 protected:
00095   void pre_delete_extra_data() {
00096     if(extra_data_map_) impl_pre_delete_extra_data();
00097   }
00098 private:
00099   struct extra_data_entry_t {
00100     extra_data_entry_t() : destroy_when(POST_DESTROY) {}
00101     extra_data_entry_t( const any &_extra_data, EPrePostDestruction _destroy_when )
00102       : extra_data(_extra_data), destroy_when(_destroy_when) {}
00103     any extra_data;
00104     EPrePostDestruction destroy_when;
00105   };  
00106   typedef Teuchos::map<std::string,extra_data_entry_t> extra_data_map_t;
00107   int                 count_;
00108   bool                has_ownership_;
00109   extra_data_map_t    *extra_data_map_;
00110   // Above is made a pointer to reduce overhead for the general case
00111   // where this is not used
00112   void impl_pre_delete_extra_data();
00113   // Not defined and not to be called
00114   RefCountPtr_node();
00115   RefCountPtr_node(const RefCountPtr_node&);
00116   RefCountPtr_node& operator=(const RefCountPtr_node&);
00117 };  // end class RefCountPtr_node;
00118 
00119 // Implementation class for actually deleting the object if has_ownership() == true.
00120 template<class T, class Dealloc_T>
00121 class RefCountPtr_node_tmpl : public RefCountPtr_node {
00122 public:
00123 
00124   //
00125   RefCountPtr_node_tmpl(T* p, Dealloc_T dealloc, bool has_ownership)
00126     : RefCountPtr_node(has_ownership), ptr_(p), dealloc_(dealloc)
00127   {}
00128   //
00129   Dealloc_T& get_dealloc() { return dealloc_; }
00130   //
00131   const Dealloc_T& get_dealloc() const { return dealloc_; }
00132   //
00133   ~RefCountPtr_node_tmpl() {
00134     this->pre_delete_extra_data();
00135     if( has_ownership() )
00136       dealloc_.free(ptr_);
00137   }
00138 
00139 private:
00140 
00141   T           *ptr_;
00142   Dealloc_T   dealloc_;
00143   // not defined and not to be called
00144   RefCountPtr_node_tmpl();
00145   RefCountPtr_node_tmpl(const RefCountPtr_node_tmpl&);
00146   RefCountPtr_node_tmpl& operator=(const RefCountPtr_node_tmpl&);
00147 
00148 }; // end class RefCountPtr_node_tmpl<T>
00149 
00150 } // end namespace PrivateUtilityPack 
00151 
00152 #endif
00153 
00154 // /////////////////////////////////////////////////////////////////////////////////
00155 // Inline member functions for RefCountPtr<...>.
00156 
00157 template<class T>
00158 inline
00159 RefCountPtr<T>::RefCountPtr( ENull )
00160   : ptr_(NULL)
00161   , node_(NULL)
00162 {}
00163 
00164 template<class T>
00165 REFCOUNTPTR_INLINE
00166 RefCountPtr<T>::RefCountPtr(const RefCountPtr<T>& r_ptr)
00167   : ptr_(r_ptr.ptr_), node_(r_ptr.node_)
00168 {
00169   if(node_) node_->incr_count();
00170 }
00171 
00172 template<class T>
00173 REFCOUNTPTR_INLINE
00174 template <class T2>
00175 RefCountPtr<T>::RefCountPtr(const RefCountPtr<T2>& r_ptr)
00176   : ptr_(const_cast<T2*>(r_ptr.get()))                 // will not compile if T1 is not an ancestor of T2
00177   , node_(const_cast<node_t*>(r_ptr.access_node()))
00178 {
00179   if(node_) node_->incr_count();
00180 }
00181 
00182 template<class T>
00183 REFCOUNTPTR_INLINE
00184 RefCountPtr<T>::~RefCountPtr()
00185 {
00186   if(node_ && node_->deincr_count() == 0 ) delete node_;
00187 }
00188 
00189 template<class T>
00190 REFCOUNTPTR_INLINE
00191 RefCountPtr<T>& RefCountPtr<T>::operator=(const RefCountPtr<T>& r_ptr) {
00192   if(node_) {
00193     if( r_ptr.node_ == node_ )
00194       return *this; // Assignment to self!
00195     if( !node_->deincr_count() ) {
00196       delete node_;
00197     }
00198   }
00199   ptr_  = r_ptr.ptr_;
00200   node_ = r_ptr.node_;
00201   if(node_) node_->incr_count();
00202   return *this;
00203 }
00204 
00205 template<class T>
00206 inline
00207 T* RefCountPtr<T>::operator->() const {
00208 #ifdef _DEBUG
00209   assert_not_null();
00210 #endif
00211   return ptr_;
00212 }
00213 
00214 template<class T>
00215 inline
00216 T& RefCountPtr<T>::operator*() const {
00217 #ifdef _DEBUG
00218   assert_not_null();
00219 #endif
00220   return *ptr_;
00221 }
00222 
00223 template<class T>
00224 inline
00225 T* RefCountPtr<T>::get() const {
00226   return ptr_;
00227 }
00228 
00229 template<class T>
00230 REFCOUNTPTR_INLINE
00231 T* RefCountPtr<T>::release() {
00232   if(node_)
00233     node_->has_ownership(false);
00234   return ptr_;
00235 }
00236 
00237 template<class T>
00238 REFCOUNTPTR_INLINE
00239 int RefCountPtr<T>::count() const {
00240   if(node_)
00241     return node_->count();
00242   return 0;
00243 }
00244 
00245 template<class T>
00246 REFCOUNTPTR_INLINE
00247 void RefCountPtr<T>::set_has_ownership() {
00248   if(node_)
00249     node_->has_ownership(true);
00250 }
00251 
00252 template<class T>
00253 REFCOUNTPTR_INLINE
00254 bool RefCountPtr<T>::has_ownership() const {
00255   if(node_)
00256     return node_->has_ownership();
00257   return false;
00258 }
00259 
00260 template<class T>
00261 REFCOUNTPTR_INLINE
00262 bool RefCountPtr<T>::shares_resource(const RefCountPtr<T>& r_ptr) const {
00263   return node_ == r_ptr.node_;
00264 }
00265 
00266 template<class T>
00267 inline
00268 const RefCountPtr<T>& RefCountPtr<T>::assert_not_null() const {
00269   if(!ptr_) PrivateUtilityPack::throw_null(typeid(T).name());
00270   return *this;
00271 }
00272 
00273 // very bad public functions
00274 
00275 template<class T>
00276 inline
00277 RefCountPtr<T>::RefCountPtr( T* p, bool has_ownership )
00278   : ptr_(p)
00279   , node_( p ? new PrivateUtilityPack::RefCountPtr_node_tmpl<T,DeallocDelete<T> >(p,DeallocDelete<T>(),has_ownership) : NULL )
00280 {}
00281 
00282 template<class T>
00283 REFCOUNTPTR_INLINE
00284 template<class Dealloc_T>
00285 RefCountPtr<T>::RefCountPtr( T* p, Dealloc_T dealloc, bool has_ownership )
00286   : ptr_(p)
00287   , node_( p ? new PrivateUtilityPack::RefCountPtr_node_tmpl<T,Dealloc_T>(p,dealloc,has_ownership) : NULL )
00288 {}
00289 
00290 template<class T>
00291 inline
00292 RefCountPtr<T>::RefCountPtr( T* p, node_t* node)
00293   : ptr_(p), node_(node)
00294 {
00295   if(node_) node_->incr_count();
00296 }
00297 
00298 template<class T>
00299 inline
00300 T*& RefCountPtr<T>::access_ptr()
00301 { return ptr_; }
00302 
00303 template<class T>
00304 inline
00305 typename RefCountPtr<T>::node_t*& RefCountPtr<T>::access_node()
00306 { return node_; }
00307 
00308 template<class T>
00309 inline
00310 typename RefCountPtr<T>::node_t* RefCountPtr<T>::access_node() const
00311 { return node_; }
00312 
00313 } // end namespace Teuchos
00314 
00315 // /////////////////////////////////////////////////////////////////////////////////
00316 // Inline non-member functions for RefCountPtr
00317 
00318 template<class T>
00319 inline
00320 Teuchos::RefCountPtr<T>
00321 Teuchos::rcp( T* p, bool owns_mem )
00322 {
00323   return RefCountPtr<T>(p,owns_mem);
00324 }
00325 
00326 template<class T, class Dealloc_T>
00327 inline
00328 Teuchos::RefCountPtr<T>
00329 Teuchos::rcp( T* p, Dealloc_T dealloc, bool owns_mem )
00330 {
00331   return RefCountPtr<T>(p,dealloc,owns_mem);
00332 }
00333 
00334 template<class T>
00335 REFCOUNTPTR_INLINE
00336 bool Teuchos::is_null( const RefCountPtr<T> &p )
00337 {
00338   return p.get() == NULL;
00339 }
00340 
00341 template<class T>
00342 REFCOUNTPTR_INLINE
00343 bool Teuchos::operator==( const RefCountPtr<T> &p, ENull )
00344 {
00345   return p.get() == NULL;
00346 }
00347 
00348 template<class T>
00349 REFCOUNTPTR_INLINE
00350 bool Teuchos::operator!=( const RefCountPtr<T> &p, ENull )
00351 {
00352   return p.get() != NULL;
00353 }
00354 
00355 template<class T1, class T2>
00356 REFCOUNTPTR_INLINE
00357 bool Teuchos::operator==( const RefCountPtr<T1> &p1, const RefCountPtr<T2> &p2 )
00358 {
00359   return p1.access_node() == p2.access_node();
00360 }
00361 
00362 template<class T1, class T2>
00363 REFCOUNTPTR_INLINE
00364 bool Teuchos::operator!=( const RefCountPtr<T1> &p1, const RefCountPtr<T2> &p2 )
00365 {
00366   return p1.access_node() != p2.access_node();
00367 }
00368 
00369 template<class T2, class T1>
00370 REFCOUNTPTR_INLINE
00371 Teuchos::RefCountPtr<T2>
00372 Teuchos::rcp_implicit_cast(const RefCountPtr<T1>& p1)
00373 {
00374   T2 *check = p1.get(); // Make the compiler check if the conversion is legal
00375   RefCountPtr<T2> p2;
00376   if(p1.access_node()) {
00377     p2.access_ptr()  = check;
00378     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00379     p2.access_node()->incr_count();
00380   }
00381   return p2;
00382 }
00383 
00384 template<class T2, class T1>
00385 REFCOUNTPTR_INLINE
00386 Teuchos::RefCountPtr<T2>
00387 Teuchos::rcp_static_cast(const RefCountPtr<T1>& p1)
00388 {
00389   T2 *check = static_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00390   RefCountPtr<T2> p2;
00391   if(p1.access_node()) {
00392     p2.access_ptr()  = check;
00393     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00394     p2.access_node()->incr_count();
00395   }
00396   return p2;
00397 }
00398 
00399 template<class T2, class T1>
00400 REFCOUNTPTR_INLINE
00401 Teuchos::RefCountPtr<T2>
00402 Teuchos::rcp_const_cast(const RefCountPtr<T1>& p1)
00403 {
00404   T2 *check = const_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00405   RefCountPtr<T2> p2;
00406   if(p1.access_node()) {
00407     p2.access_ptr()  = check;
00408     p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00409     p2.access_node()->incr_count();
00410   }
00411   return p2;
00412 }
00413 
00414 template<class T2, class T1>
00415 REFCOUNTPTR_INLINE
00416 Teuchos::RefCountPtr<T2>
00417 Teuchos::rcp_dynamic_cast(const RefCountPtr<T1>& p1, bool throw_on_fail)
00418 {
00419   RefCountPtr<T2> p2; // NULL by default
00420   if( p1.get() ) {
00421     T2 *check = NULL;
00422     if(throw_on_fail)
00423       check = &dyn_cast<T2>(*p1);
00424     else
00425       check = dynamic_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00426     if(check) {
00427       p2.access_ptr()  = check;
00428       p2.access_node() = const_cast<RefCountPtr<T1>&>(p1).access_node();
00429       p2.access_node()->incr_count();
00430     }
00431   }
00432   return p2;
00433 }
00434 
00435 template<class T1, class T2>
00436 REFCOUNTPTR_INLINE
00437 void Teuchos::set_extra_data( const T1 &extra_data, const std::string& name, Teuchos::RefCountPtr<T2> *p, bool force_unique, EPrePostDestruction destroy_when )
00438 {
00439   p->assert_not_null();
00440   p->access_node()->set_extra_data( extra_data, name, force_unique, destroy_when );
00441 }
00442 
00443 template<class T1, class T2>
00444 REFCOUNTPTR_INLINE
00445 T1& Teuchos::get_extra_data( RefCountPtr<T2>& p, const std::string& name )
00446 {
00447   p.assert_not_null();
00448   return any_cast<T1>(p.access_node()->get_extra_data(typeid(T1).name(),name));
00449 }
00450 
00451 template<class T1, class T2>
00452 REFCOUNTPTR_INLINE
00453 const T1& Teuchos::get_extra_data( const RefCountPtr<T2>& p, const std::string& name )
00454 {
00455   p.assert_not_null();
00456   return any_cast<T1>(p.access_node()->get_extra_data(typeid(T1).name(),name));
00457 }
00458 
00459 template<class T1, class T2>
00460 REFCOUNTPTR_INLINE
00461 T1* Teuchos::get_optional_extra_data( RefCountPtr<T2>& p, const std::string& name )
00462 {
00463   p.assert_not_null();
00464   any *extra_data = p.access_node()->get_optional_extra_data(typeid(T1).name(),name);
00465   if( extra_data ) return &any_cast<T1>(*extra_data);
00466   return NULL;
00467 }
00468 
00469 template<class T1, class T2>
00470 REFCOUNTPTR_INLINE
00471 const T1* Teuchos::get_optional_extra_data( const RefCountPtr<T2>& p, const std::string& name )
00472 {
00473   p.assert_not_null();
00474   any *extra_data = p.access_node()->get_optional_extra_data(typeid(T1).name(),name);
00475   if( extra_data ) return &any_cast<T1>(*extra_data);
00476   return NULL;
00477 }
00478 
00479 template<class Dealloc_T, class T>
00480 REFCOUNTPTR_INLINE
00481 Dealloc_T&
00482 Teuchos::get_dealloc( RefCountPtr<T>& p )
00483 {
00484   p.assert_not_null();
00485   PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00486     *dnode = dynamic_cast<PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(p.access_node());
00487   TEST_FOR_EXCEPTION(
00488     dnode==NULL, std::logic_error
00489     ,"get_dealloc<" << typeid(Dealloc_T).name() << "," << typeid(T).name() << ">(p): "
00490     << "Error, requested type \'" << typeid(PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>).name()
00491     << "\' does not match actual type of the node \'" << typeid(*p.access_node()).name() << "!"
00492     );
00493   return dnode->get_dealloc();
00494 }
00495 
00496 template<class Dealloc_T, class T>
00497 inline
00498 const Dealloc_T& 
00499 Teuchos::get_dealloc( const Teuchos::RefCountPtr<T>& p )
00500 {
00501   return get_dealloc<Dealloc_T>(const_cast<RefCountPtr<T>&>(p));
00502 }
00503 
00504 template<class Dealloc_T, class T>
00505 REFCOUNTPTR_INLINE
00506 Dealloc_T*
00507 Teuchos::get_optional_dealloc( RefCountPtr<T>& p )
00508 {
00509   p.assert_not_null();
00510   PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00511     *dnode = dynamic_cast<PrivateUtilityPack::RefCountPtr_node_tmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(p.access_node());
00512   if(dnode)
00513     return &dnode->get_dealloc();
00514   return NULL;
00515 }
00516 
00517 template<class Dealloc_T, class T>
00518 inline
00519 const Dealloc_T*
00520 Teuchos::get_optional_dealloc( const Teuchos::RefCountPtr<T>& p )
00521 {
00522   return get_optional_dealloc<Dealloc_T>(const_cast<RefCountPtr<T>&>(p));
00523 }
00524 
00525 #endif // TEUCHOS_REFCOUNTPTR_HPP

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