Teuchos_RCP.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_RCP_HPP
00030 #define TEUCHOS_RCP_HPP
00031 
00032 
00045 #include "Teuchos_RCPDecl.hpp"
00046 #include "Teuchos_TestForException.hpp"
00047 #include "Teuchos_Exceptions.hpp"
00048 #include "Teuchos_dyn_cast.hpp"
00049 #include "Teuchos_map.hpp"
00050 #include "Teuchos_TypeNameTraits.hpp"
00051 
00052 
00053 // /////////////////////////////////////////////////////////////////////////
00054 // Inline implementations below, not for the client to look at.
00055 
00056 namespace Teuchos {
00057 
00058 
00059 // /////////////////////////////////////////////////////////////////////////////////
00060 // Inline member functions for RCP<...>.
00061 
00062 
00063 template<class T>
00064 inline
00065 RCP<T>::RCP( ENull )
00066   : ptr_(NULL)
00067   , node_(NULL)
00068 {}
00069 
00070 
00071 template<class T>
00072 REFCOUNTPTR_INLINE
00073 RCP<T>::RCP(const RCP<T>& r_ptr)
00074   : ptr_(r_ptr.ptr_), node_(r_ptr.node_)
00075 {
00076   if(node_) node_->incr_count();
00077 }
00078 
00079 
00080 template<class T>
00081 REFCOUNTPTR_INLINE
00082 template<class T2>
00083 RCP<T>::RCP(const RCP<T2>& r_ptr)
00084   : ptr_(r_ptr.get()),  // will not compile if T is not base class of T2
00085     node_(r_ptr.access_node())
00086 {
00087   if(node_) node_->incr_count();
00088 }
00089 
00090 
00091 template<class T>
00092 REFCOUNTPTR_INLINE
00093 RCP<T>::~RCP()
00094 {
00095   if(node_ && node_->deincr_count() == 0 ) {
00096 #ifdef TEUCHOS_DEBUG
00097     local_printActiveRCPNodes.foo(); // Make sure this object is used!
00098     remove_RCPNode(node_);
00099 #endif
00100     delete node_;
00101   }
00102 }
00103 
00104 
00105 template<class T>
00106 REFCOUNTPTR_INLINE
00107 RCP<T>& RCP<T>::operator=(const RCP<T>& r_ptr)
00108 {
00109   if( this == &r_ptr )
00110     return *this; // Assignment to self
00111   if( node_ && !node_->deincr_count() ) {
00112 #ifdef TEUCHOS_DEBUG
00113     remove_RCPNode(node_);
00114 #endif
00115     delete node_;
00116   }
00117   ptr_  = r_ptr.ptr_;
00118   node_ = r_ptr.node_;
00119   if(node_) node_->incr_count();
00120   return *this;
00121 }
00122 
00123 
00124 template<class T>
00125 inline
00126 T* RCP<T>::operator->() const
00127 {
00128 #ifdef TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL
00129   assert_not_null();
00130 #endif
00131   return ptr_;
00132 }
00133 
00134 
00135 template<class T>
00136 inline
00137 T& RCP<T>::operator*() const
00138 {
00139 #ifdef TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL
00140   assert_not_null();
00141 #endif
00142   return *ptr_;
00143 }
00144 
00145 
00146 template<class T>
00147 inline
00148 T* RCP<T>::get() const
00149 {
00150   return ptr_;
00151 }
00152 
00153 
00154 template<class T>
00155 inline
00156 T* RCP<T>::getRawPtr() const
00157 {
00158   return ptr_;
00159 }
00160 
00161 
00162 template<class T>
00163 inline
00164 Ptr<T> RCP<T>::ptr() const
00165 {
00166   return Ptr<T>(ptr_);
00167 }
00168 
00169 
00170 template<class T>
00171 REFCOUNTPTR_INLINE
00172 Ptr<T> RCP<T>::release() {
00173   if(node_)
00174     node_->has_ownership(false);
00175   return Ptr<T>(ptr_);
00176 }
00177 
00178 
00179 template<class T>
00180 REFCOUNTPTR_INLINE
00181 int RCP<T>::count() const
00182 {
00183   if(node_)
00184     return node_->count();
00185   return 0;
00186 }
00187 
00188 
00189 template<class T>
00190 REFCOUNTPTR_INLINE
00191 void RCP<T>::set_has_ownership() {
00192   if(node_)
00193     node_->has_ownership(true);
00194 }
00195 
00196 
00197 template<class T>
00198 REFCOUNTPTR_INLINE
00199 bool RCP<T>::has_ownership() const
00200 {
00201   if(node_)
00202     return node_->has_ownership();
00203   return false;
00204 }
00205 
00206 
00207 template<class T>
00208 REFCOUNTPTR_INLINE
00209 template <class T2>
00210 bool RCP<T>::shares_resource(const RCP<T2>& r_ptr) const
00211 {
00212   return node_ == r_ptr.access_node();
00213   // Note: above, r_ptr is *not* the same class type as *this so we can not
00214   // access its node_ member directly!  This is an interesting detail to the
00215   // C++ protected/private protection mechanism!
00216 }
00217 
00218 
00219 template<class T>
00220 inline
00221 const RCP<T>& RCP<T>::assert_not_null() const
00222 {
00223   if(!ptr_) throw_null_ptr_error(typeName(*this));
00224   return *this;
00225 }
00226 
00227 
00228 // very bad public functions
00229 
00230 
00231 template<class T>
00232 inline
00233 RCP<T>::RCP( T* p, bool has_ownership_in )
00234   :ptr_(p),
00235   node_(
00236     p
00237     ? new RCPNodeTmpl<T,DeallocDelete<T> >(p,DeallocDelete<T>(),has_ownership_in)
00238     : NULL )
00239 {
00240 #ifdef TEUCHOS_DEBUG
00241   if(node_ && isTracingActiveRCPNodes()) {
00242     std::ostringstream os;
00243     os << "{T=\'"<<typeName(p)<<"\',Concrete T=\'"
00244        <<typeName(*p)<<"\',p="<<p<<",has_ownership="<<has_ownership_in<<"}";
00245     add_new_RCPNode(node_, os.str());
00246   }
00247 #endif
00248 }
00249 
00250 
00251 template<class T>
00252 REFCOUNTPTR_INLINE
00253 template<class Dealloc_T>
00254 RCP<T>::RCP( T* p, Dealloc_T dealloc, bool has_ownership_in )
00255   : ptr_(p)
00256   , node_( p ? new RCPNodeTmpl<T,Dealloc_T>(p,dealloc,has_ownership_in) : NULL )
00257 {
00258 #ifdef TEUCHOS_DEBUG
00259   if(node_ && isTracingActiveRCPNodes()) {
00260     std::ostringstream os;
00261     os << "{T=\'"<<TypeNameTraits<T>::name()<<"\',Concrete T=\'"
00262        <<TypeNameTraits<T>::concreteName(*p)<<"\',p="
00263        <<p<<",has_ownership="<<has_ownership_in<<"}";
00264     add_new_RCPNode(node_, os.str());
00265   }
00266 #endif
00267 }
00268 
00269 
00270 template<class T>
00271 inline
00272 RCP<T>::RCP( T* p, RCPNode* node)
00273   : ptr_(p), node_(node)
00274 {
00275   if(node_) node_->incr_count();
00276 }
00277 
00278 
00279 template<class T>
00280 inline
00281 T*& RCP<T>::access_ptr()
00282 {  return ptr_; }
00283 
00284 
00285 template<class T>
00286 inline
00287 RCPNode*& RCP<T>::access_node()
00288 {  return node_; }
00289 
00290 
00291 template<class T>
00292 inline
00293 RCPNode* RCP<T>::access_node() const
00294 {  return node_; }
00295 
00296 
00297 }  // end namespace Teuchos
00298 
00299 
00300 // /////////////////////////////////////////////////////////////////////////////////
00301 // Inline non-member functions for RCP
00302 
00303 
00304 template<class T>
00305 inline
00306 Teuchos::RCP<T>
00307 Teuchos::rcp( T* p, bool owns_mem )
00308 {
00309   return RCP<T>(p, owns_mem);
00310 }
00311 
00312 
00313 template<class T, class Dealloc_T>
00314 inline
00315 Teuchos::RCP<T>
00316 Teuchos::rcp( T* p, Dealloc_T dealloc, bool owns_mem )
00317 {
00318   return RCP<T>(p, dealloc, owns_mem);
00319 }
00320 
00321 
00322 template<class T>
00323 Teuchos::RCP<T>
00324 Teuchos::rcpFromRef( T& r )
00325 {
00326   return Teuchos::rcp(&r, false);
00327 }
00328 
00329 
00330 template<class T, class Embedded>
00331 Teuchos::RCP<T>
00332 Teuchos::rcpWithEmbeddedObjPreDestroy(
00333   T* p, const Embedded &embedded, bool owns_mem
00334   )
00335 {
00336   return rcp(
00337     p, embeddedObjDeallocDelete<T>(embedded,PRE_DESTROY), owns_mem
00338     );
00339 }
00340 
00341 
00342 template<class T, class Embedded>
00343 Teuchos::RCP<T>
00344 Teuchos::rcpWithEmbeddedObjPostDestroy(
00345   T* p, const Embedded &embedded, bool owns_mem
00346   )
00347 {
00348   return rcp( p, embeddedObjDeallocDelete<T>(embedded,POST_DESTROY), owns_mem );
00349 }
00350 
00351 
00352 template<class T, class Embedded>
00353 Teuchos::RCP<T>
00354 Teuchos::rcpWithEmbeddedObj( T* p, const Embedded &embedded, bool owns_mem )
00355 {
00356   return rcpWithEmbeddedObjPostDestroy<T,Embedded>(p,embedded,owns_mem);
00357 }
00358 
00359 
00360 template<class T>
00361 REFCOUNTPTR_INLINE
00362 bool Teuchos::is_null( const RCP<T> &p )
00363 {
00364   return p.get() == NULL;
00365 }
00366 
00367 
00368 template<class T>
00369 REFCOUNTPTR_INLINE
00370 bool Teuchos::operator==( const RCP<T> &p, ENull )
00371 {
00372   return p.get() == NULL;
00373 }
00374 
00375 
00376 template<class T>
00377 REFCOUNTPTR_INLINE
00378 bool Teuchos::operator!=( const RCP<T> &p, ENull )
00379 {
00380   return p.get() != NULL;
00381 }
00382 
00383 
00384 template<class T1, class T2>
00385 REFCOUNTPTR_INLINE
00386 bool Teuchos::operator==( const RCP<T1> &p1, const RCP<T2> &p2 )
00387 {
00388   return p1.access_node() == p2.access_node();
00389 }
00390 
00391 
00392 template<class T1, class T2>
00393 REFCOUNTPTR_INLINE
00394 bool Teuchos::operator!=( const RCP<T1> &p1, const RCP<T2> &p2 )
00395 {
00396   return p1.access_node() != p2.access_node();
00397 }
00398 
00399 
00400 template<class T2, class T1>
00401 REFCOUNTPTR_INLINE
00402 Teuchos::RCP<T2>
00403 Teuchos::rcp_implicit_cast(const RCP<T1>& p1)
00404 {
00405   T2 *check = p1.get();  // Make the compiler check if the conversion is legal
00406   RCP<T2> p2;
00407   if(p1.access_node()) {
00408     p2.access_ptr()  = check;
00409     p2.access_node() = const_cast<RCP<T1>&>(p1).access_node();
00410     p2.access_node()->incr_count();
00411   }
00412   return p2;
00413 }
00414 
00415 
00416 template<class T2, class T1>
00417 REFCOUNTPTR_INLINE
00418 Teuchos::RCP<T2>
00419 Teuchos::rcp_static_cast(const RCP<T1>& p1)
00420 {
00421   T2 *check = static_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00422   RCP<T2> p2;
00423   if(p1.access_node()) {
00424     p2.access_ptr()  = check;
00425     p2.access_node() = const_cast<RCP<T1>&>(p1).access_node();
00426     p2.access_node()->incr_count();
00427   }
00428   return p2;
00429 }
00430 
00431 
00432 template<class T2, class T1>
00433 REFCOUNTPTR_INLINE
00434 Teuchos::RCP<T2>
00435 Teuchos::rcp_const_cast(const RCP<T1>& p1)
00436 {
00437   T2 *check = const_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00438   RCP<T2> p2;
00439   if(p1.access_node()) {
00440     p2.access_ptr()  = check;
00441     p2.access_node() = const_cast<RCP<T1>&>(p1).access_node();
00442     p2.access_node()->incr_count();
00443   }
00444   return p2;
00445 }
00446 
00447 
00448 template<class T2, class T1>
00449 REFCOUNTPTR_INLINE
00450 Teuchos::RCP<T2>
00451 Teuchos::rcp_dynamic_cast(const RCP<T1>& p1, bool throw_on_fail)
00452 {
00453   RCP<T2> p2; // NULL by default
00454   if (!is_null(p1)) {
00455     T2 *p = NULL;
00456     if (throw_on_fail)
00457       p = &dyn_cast<T2>(*p1);
00458     else
00459       p = dynamic_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
00460     if (p) {
00461       p2.access_ptr() = p;
00462       p2.access_node() = p1.access_node();
00463       p2.access_node()->incr_count();
00464     }
00465   }
00466   return p2;
00467 }
00468 
00469 
00470 template<class T1, class T2>
00471 REFCOUNTPTR_INLINE
00472 void Teuchos::set_extra_data( const T1 &extra_data, const std::string& name, Teuchos::RCP<T2> *p, EPrePostDestruction destroy_when, bool force_unique )
00473 {
00474   p->assert_not_null();
00475   p->access_node()->set_extra_data( any(extra_data), name, destroy_when, force_unique );
00476 }
00477 
00478 
00479 template<class T1, class T2>
00480 REFCOUNTPTR_INLINE
00481 const T1& Teuchos::get_extra_data( const RCP<T2>& p, const std::string& name )
00482 {
00483   p.assert_not_null();
00484   return any_cast<T1>(p.access_node()->get_extra_data(TypeNameTraits<T1>::name(),name));
00485 }
00486 
00487 
00488 template<class T1, class T2>
00489 REFCOUNTPTR_INLINE
00490 T1& Teuchos::get_nonconst_extra_data( const RCP<T2>& p, const std::string& name )
00491 {
00492   p.assert_not_null();
00493   return any_cast<T1>(p.access_node()->get_extra_data(TypeNameTraits<T1>::name(),name));
00494 }
00495 
00496 
00497 template<class T1, class T2>
00498 REFCOUNTPTR_INLINE
00499 Teuchos::Ptr<const T1>
00500 Teuchos::get_optional_extra_data( const RCP<T2>& p, const std::string& name )
00501 {
00502   p.assert_not_null();
00503   any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits<T1>::name(),name);
00504   if( extra_data ) return Ptr<const T1>(&any_cast<T1>(*extra_data));
00505   return null;
00506 }
00507 
00508 
00509 template<class T1, class T2>
00510 REFCOUNTPTR_INLINE
00511 Teuchos::Ptr<T1>
00512 Teuchos::get_optional_nonconst_extra_data( const RCP<T2>& p, const std::string& name )
00513 {
00514   p.assert_not_null();
00515   any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits<T1>::name(),name);
00516   if( extra_data ) return Ptr<T1>(&any_cast<T1>(*extra_data));
00517   return null;
00518 }
00519 
00520 
00521 template<class Dealloc_T, class T>
00522 inline
00523 const Dealloc_T& Teuchos::get_dealloc( const RCP<T>& p )
00524 {
00525   return get_nonconst_dealloc<Dealloc_T>(const_cast<RCP<T>&>(p));
00526 }
00527 
00528 
00529 template<class Dealloc_T, class T>
00530 REFCOUNTPTR_INLINE
00531 Dealloc_T& Teuchos::get_nonconst_dealloc( const RCP<T>& p )
00532 {
00533   typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>  requested_type;
00534   p.assert_not_null();
00535   RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00536     *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(p.access_node());
00537   TEST_FOR_EXCEPTION(
00538     dnode==NULL, NullReferenceError
00539     ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name() << "," << TypeNameTraits<T>::name() << ">(p): "
00540     << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
00541     << "\' does not match actual type of the node \'" << typeName(*p.access_node()) << "!"
00542     );
00543   return dnode->get_nonconst_dealloc();
00544 }
00545 
00546 
00547 template<class Dealloc_T, class T>
00548 REFCOUNTPTR_INLINE
00549 Teuchos::Ptr<Dealloc_T>
00550 Teuchos::get_optional_nonconst_dealloc( const RCP<T>& p )
00551 {
00552   p.assert_not_null();
00553   RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00554     *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(p.access_node());
00555   if(dnode)
00556     return ptr(&dnode->get_nonconst_dealloc());
00557   return null;
00558 }
00559 
00560 
00561 template<class Dealloc_T, class T>
00562 inline
00563 Teuchos::Ptr<const Dealloc_T>
00564 Teuchos::get_optional_dealloc( const RCP<T>& p )
00565 {
00566   return get_optional_nonconst_dealloc<Dealloc_T>(const_cast<RCP<T>&>(p));
00567 }
00568 
00569 
00570 template<class TOrig, class Embedded, class T>
00571 const Embedded& Teuchos::getEmbeddedObj( const RCP<T>& p )
00572 {
00573   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00574   return get_dealloc<Dealloc_t>(p).getObj();
00575 }
00576 
00577 
00578 template<class TOrig, class Embedded, class T>
00579 Embedded& Teuchos::getNonconstEmbeddedObj( const RCP<T>& p )
00580 {
00581   typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00582   return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
00583 }
00584 
00585 
00586 template<class T>
00587 std::ostream& Teuchos::operator<<( std::ostream& out, const RCP<T>& p )
00588 {
00589   out
00590     << TypeNameTraits<RCP<T> >::name() << "{"
00591     << "ptr="<<(const void*)(p.get()) // I can't find any alternative to this C cast :-(
00592     <<",node="<<p.access_node()
00593     <<",count="<<p.count()
00594     <<"}";
00595   return out;
00596 }
00597 
00598 
00599 #endif // TEUCHOS_RCP_HPP

Generated on Wed May 12 21:40:32 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7