00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00055
00056 namespace Teuchos {
00057
00058
00059
00060
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()),
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();
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;
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
00214
00215
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
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 }
00298
00299
00300
00301
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();
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());
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());
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;
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());
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())
00592 <<",node="<<p.access_node()
00593 <<",count="<<p.count()
00594 <<"}";
00595 return out;
00596 }
00597
00598
00599 #endif // TEUCHOS_RCP_HPP