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_Ptr.hpp"
00047 #include "Teuchos_TestForException.hpp"
00048 #include "Teuchos_Exceptions.hpp"
00049 #include "Teuchos_dyn_cast.hpp"
00050 #include "Teuchos_map.hpp"
00051 #include "Teuchos_TypeNameTraits.hpp"
00052
00053
00054 namespace Teuchos {
00055
00056
00057
00058
00059
00060 template<class T>
00061 inline
00062 RCP<T>::RCP( ENull )
00063 : ptr_(NULL)
00064 {}
00065
00066
00067 template<class T>
00068 inline
00069 RCP<T>::RCP( T* p, ENull null_arg )
00070 : ptr_(p)
00071 #ifndef TEUCHOS_DEBUG
00072 , node_(RCP_createNewRCPNodeRawPtrNonowned(p))
00073 #endif
00074 {
00075 #ifdef TEUCHOS_DEBUG
00076 if (p) {
00077 node_ = RCPNodeHandle(
00078 RCP_createNewRCPNodeRawPtrNonowned(p),
00079 p, typeName(*p), concreteTypeName(*p),
00080 false
00081 );
00082 }
00083 #endif // TEUCHOS_DEBUG
00084 }
00085
00086
00087 template<class T>
00088 inline
00089 RCP<T>::RCP( T* p, bool has_ownership_in )
00090 : ptr_(p)
00091 #ifndef TEUCHOS_DEBUG
00092 , node_(RCP_createNewRCPNodeRawPtr(p, has_ownership_in))
00093 #endif
00094 {
00095 #ifdef TEUCHOS_DEBUG
00096 if (p) {
00097 node_ = RCPNodeHandle(
00098 RCP_createNewRCPNodeRawPtr(p, has_ownership_in),
00099 p, typeName(*p), concreteTypeName(*p),
00100 has_ownership_in
00101 );
00102 }
00103 #endif // TEUCHOS_DEBUG
00104 }
00105
00106
00107 template<class T>
00108 REFCOUNTPTR_INLINE
00109 template<class Dealloc_T>
00110 RCP<T>::RCP( T* p, Dealloc_T dealloc, bool has_ownership_in )
00111 : ptr_(p)
00112 #ifndef TEUCHOS_DEBUG
00113 , node_(RCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in))
00114 #endif
00115 {
00116 #ifdef TEUCHOS_DEBUG
00117 if (p) {
00118 node_ = RCPNodeHandle(
00119 RCP_createNewDeallocRCPNodeRawPtr(p, dealloc, has_ownership_in),
00120 p, typeName(*p), concreteTypeName(*p),
00121 has_ownership_in
00122 );
00123 }
00124 #endif // TEUCHOS_DEBUG
00125 }
00126
00127
00128 template<class T>
00129 REFCOUNTPTR_INLINE
00130 RCP<T>::RCP(const RCP<T>& r_ptr)
00131 : ptr_(r_ptr.ptr_), node_(r_ptr.node_)
00132 {}
00133
00134
00135 template<class T>
00136 REFCOUNTPTR_INLINE
00137 template<class T2>
00138 RCP<T>::RCP(const RCP<T2>& r_ptr)
00139 : ptr_(r_ptr.get()),
00140 node_(r_ptr.access_private_node())
00141 {}
00142
00143
00144 template<class T>
00145 REFCOUNTPTR_INLINE
00146 RCP<T>::~RCP()
00147 {}
00148
00149
00150 template<class T>
00151 REFCOUNTPTR_INLINE
00152 RCP<T>& RCP<T>::operator=(const RCP<T>& r_ptr)
00153 {
00154 if( this == &r_ptr )
00155 return *this;
00156 node_ = r_ptr.access_private_node();
00157 ptr_ = r_ptr.ptr_;
00158 return *this;
00159
00160
00161 }
00162
00163
00164 template<class T>
00165 REFCOUNTPTR_INLINE
00166 template<class T2>
00167 void RCP<T>::reset(T2* p, bool has_ownership_in)
00168 {
00169 *this = rcp(p, has_ownership_in);
00170 }
00171
00172
00173
00174
00175
00176 template<class T>
00177 inline
00178 bool RCP<T>::is_null() const
00179 {
00180 return ptr_ == 0;
00181 }
00182
00183
00184 template<class T>
00185 inline
00186 T* RCP<T>::operator->() const
00187 {
00188 debug_assert_not_null();
00189 debug_assert_valid_ptr();
00190 return ptr_;
00191 }
00192
00193
00194 template<class T>
00195 inline
00196 T& RCP<T>::operator*() const
00197 {
00198 debug_assert_not_null();
00199 debug_assert_valid_ptr();
00200 return *ptr_;
00201 }
00202
00203 template<class T>
00204 inline
00205 T* RCP<T>::get() const
00206 {
00207 debug_assert_valid_ptr();
00208 return ptr_;
00209 }
00210
00211
00212 template<class T>
00213 inline
00214 T* RCP<T>::getRawPtr() const
00215 {
00216 return this->get();
00217 }
00218
00219
00220 template<class T>
00221 inline
00222 Ptr<T> RCP<T>::ptr() const
00223 {
00224 #ifdef TEUCHOS_DEBUG
00225 return Ptr<T>(this->create_weak());
00226 #else
00227 return Ptr<T>(getRawPtr());
00228 #endif
00229 }
00230
00231
00232
00233
00234
00235 template<class T>
00236 inline
00237 ERCPStrength RCP<T>::strength() const
00238 {
00239 return node_.strength();
00240 }
00241
00242
00243 template<class T>
00244 inline
00245 bool RCP<T>::is_valid_ptr() const
00246 {
00247 if (ptr_)
00248 return node_.is_valid_ptr();
00249 return true;
00250 }
00251
00252
00253 template<class T>
00254 inline
00255 int RCP<T>::strong_count() const
00256 {
00257 return node_.strong_count();
00258 }
00259
00260
00261 template<class T>
00262 inline
00263 int RCP<T>::weak_count() const
00264 {
00265 return node_.weak_count();
00266 }
00267
00268
00269 template<class T>
00270 inline
00271 int RCP<T>::total_count() const
00272 {
00273 return node_.total_count();
00274 }
00275
00276
00277 template<class T>
00278 REFCOUNTPTR_INLINE
00279 void RCP<T>::set_has_ownership()
00280 {
00281 node_.has_ownership(true);
00282 }
00283
00284
00285 template<class T>
00286 REFCOUNTPTR_INLINE
00287 bool RCP<T>::has_ownership() const
00288 {
00289 return node_.has_ownership();
00290 }
00291
00292
00293 template<class T>
00294 REFCOUNTPTR_INLINE
00295 Ptr<T> RCP<T>::release()
00296 {
00297 debug_assert_valid_ptr();
00298 node_.has_ownership(false);
00299 return Ptr<T>(ptr_);
00300 }
00301
00302
00303 template<class T>
00304 inline
00305 RCP<T> RCP<T>::create_weak() const
00306 {
00307 debug_assert_valid_ptr();
00308 return RCP<T>(ptr_, node_.create_weak());
00309 }
00310
00311
00312 template<class T>
00313 inline
00314 RCP<T> RCP<T>::create_strong() const
00315 {
00316 debug_assert_valid_ptr();
00317 return RCP<T>(ptr_, node_.create_strong());
00318 }
00319
00320
00321 template<class T>
00322 REFCOUNTPTR_INLINE
00323 template <class T2>
00324 bool RCP<T>::shares_resource(const RCP<T2>& r_ptr) const
00325 {
00326 return node_.same_node(r_ptr.access_private_node());
00327
00328
00329
00330 }
00331
00332
00333
00334
00335
00336 template<class T>
00337 inline
00338 const RCP<T>& RCP<T>::assert_not_null() const
00339 {
00340 if (!ptr_)
00341 throw_null_ptr_error(typeName(*this));
00342 return *this;
00343 }
00344
00345
00346 template<class T>
00347 inline
00348 const RCP<T>& RCP<T>::assert_valid_ptr() const
00349 {
00350 if (ptr_)
00351 node_.assert_valid_ptr(*this);
00352 return *this;
00353 }
00354
00355
00356
00357
00358
00359 template<class T>
00360 REFCOUNTPTR_INLINE
00361 int RCP<T>::count() const
00362 {
00363 return node_.count();
00364 }
00365
00366
00367
00368
00369
00370 template<class T>
00371 inline
00372 RCPNode* RCP_createNewRCPNodeRawPtrNonowned( T* p )
00373 {
00374 return new RCPNodeTmpl<T,DeallocNull<T> >(
00375 p, DeallocNull<T>(), false
00376 );
00377 }
00378
00379
00380 template<class T>
00381 inline
00382 RCPNode* RCP_createNewRCPNodeRawPtr( T* p, bool has_ownership_in )
00383 {
00384 return new RCPNodeTmpl<T,DeallocDelete<T> >(
00385 p, DeallocDelete<T>(), has_ownership_in
00386 );
00387 }
00388
00389
00390 template<class T, class Dealloc_T>
00391 inline
00392 RCPNode* RCP_createNewDeallocRCPNodeRawPtr(
00393 T* p, Dealloc_T dealloc, bool has_ownership_in
00394 )
00395 {
00396 return new RCPNodeTmpl<T,Dealloc_T>(p, dealloc, has_ownership_in);
00397 }
00398
00399
00400 template<class T>
00401 inline
00402 RCP<T>::RCP( T* p, const RCPNodeHandle& node)
00403 : ptr_(p), node_(node)
00404 {}
00405
00406
00407 template<class T>
00408 inline
00409 T* RCP<T>::access_private_ptr() const
00410 { return ptr_; }
00411
00412
00413 template<class T>
00414 inline
00415 RCPNodeHandle& RCP<T>::nonconst_access_private_node()
00416 { return node_; }
00417
00418
00419 template<class T>
00420 inline
00421 const RCPNodeHandle& RCP<T>::access_private_node() const
00422 { return node_; }
00423
00424
00425 }
00426
00427
00428
00429
00430
00431
00432 template<class T>
00433 inline
00434 Teuchos::RCP<T>
00435 Teuchos::rcp( T* p, bool owns_mem )
00436 {
00437 return RCP<T>(p, owns_mem);
00438 }
00439
00440
00441 template<class T, class Dealloc_T>
00442 inline
00443 Teuchos::RCP<T>
00444 Teuchos::rcp( T* p, Dealloc_T dealloc, bool owns_mem )
00445 {
00446 return RCP<T>(p, dealloc, owns_mem);
00447 }
00448
00449
00450 template<class T>
00451 Teuchos::RCP<T>
00452 Teuchos::rcpFromRef( T& r )
00453 {
00454 return RCP<T>(&r, null);
00455 }
00456
00457
00458 template<class T, class Embedded>
00459 Teuchos::RCP<T>
00460 Teuchos::rcpWithEmbeddedObjPreDestroy(
00461 T* p, const Embedded &embedded, bool owns_mem
00462 )
00463 {
00464 return rcp(
00465 p, embeddedObjDeallocDelete<T>(embedded,PRE_DESTROY), owns_mem
00466 );
00467 }
00468
00469
00470 template<class T, class Embedded>
00471 Teuchos::RCP<T>
00472 Teuchos::rcpWithEmbeddedObjPostDestroy(
00473 T* p, const Embedded &embedded, bool owns_mem
00474 )
00475 {
00476 return rcp( p, embeddedObjDeallocDelete<T>(embedded,POST_DESTROY), owns_mem );
00477 }
00478
00479
00480 template<class T, class Embedded>
00481 Teuchos::RCP<T>
00482 Teuchos::rcpWithEmbeddedObj( T* p, const Embedded &embedded, bool owns_mem )
00483 {
00484 return rcpWithEmbeddedObjPostDestroy<T,Embedded>(p,embedded,owns_mem);
00485 }
00486
00487
00488 template<class T>
00489 REFCOUNTPTR_INLINE
00490 bool Teuchos::is_null( const RCP<T> &p )
00491 {
00492 return p.is_null();
00493 }
00494
00495
00496 template<class T>
00497 REFCOUNTPTR_INLINE
00498 bool Teuchos::nonnull( const RCP<T> &p )
00499 {
00500 return !p.is_null();
00501 }
00502
00503
00504 template<class T>
00505 REFCOUNTPTR_INLINE
00506 bool Teuchos::operator==( const RCP<T> &p, ENull )
00507 {
00508 return p.get() == NULL;
00509 }
00510
00511
00512 template<class T>
00513 REFCOUNTPTR_INLINE
00514 bool Teuchos::operator!=( const RCP<T> &p, ENull )
00515 {
00516 return p.get() != NULL;
00517 }
00518
00519
00520 template<class T1, class T2>
00521 REFCOUNTPTR_INLINE
00522 bool Teuchos::operator==( const RCP<T1> &p1, const RCP<T2> &p2 )
00523 {
00524 return p1.access_private_node().same_node(p2.access_private_node());
00525 }
00526
00527
00528 template<class T1, class T2>
00529 REFCOUNTPTR_INLINE
00530 bool Teuchos::operator!=( const RCP<T1> &p1, const RCP<T2> &p2 )
00531 {
00532 return !p1.access_private_node().same_node(p2.access_private_node());
00533 }
00534
00535
00536 template<class T2, class T1>
00537 REFCOUNTPTR_INLINE
00538 Teuchos::RCP<T2>
00539 Teuchos::rcp_implicit_cast(const RCP<T1>& p1)
00540 {
00541
00542 T2 *check = p1.get();
00543 return RCP<T2>(check, p1.access_private_node());
00544 }
00545
00546
00547 template<class T2, class T1>
00548 REFCOUNTPTR_INLINE
00549 Teuchos::RCP<T2>
00550 Teuchos::rcp_static_cast(const RCP<T1>& p1)
00551 {
00552
00553 T2 *check = static_cast<T2*>(p1.get());
00554 return RCP<T2>(check, p1.access_private_node());
00555 }
00556
00557
00558 template<class T2, class T1>
00559 REFCOUNTPTR_INLINE
00560 Teuchos::RCP<T2>
00561 Teuchos::rcp_const_cast(const RCP<T1>& p1)
00562 {
00563
00564 T2 *check = const_cast<T2*>(p1.get());
00565 return RCP<T2>(check, p1.access_private_node());
00566 }
00567
00568
00569 template<class T2, class T1>
00570 REFCOUNTPTR_INLINE
00571 Teuchos::RCP<T2>
00572 Teuchos::rcp_dynamic_cast(const RCP<T1>& p1, bool throw_on_fail)
00573 {
00574 if (!is_null(p1)) {
00575 T2 *p = NULL;
00576 if (throw_on_fail) {
00577 p = &dyn_cast<T2>(*p1);
00578 }
00579 else {
00580
00581 p = dynamic_cast<T2*>(p1.get());
00582 }
00583 if (p) {
00584 return RCP<T2>(p, p1.access_private_node());
00585 }
00586 }
00587 return null;
00588 }
00589
00590
00591 template<class T1, class T2>
00592 REFCOUNTPTR_INLINE
00593 void Teuchos::set_extra_data( const T1 &extra_data, const std::string& name,
00594 const Ptr<RCP<T2> > &p, EPrePostDestruction destroy_when, bool force_unique )
00595 {
00596 p->assert_not_null();
00597 p->nonconst_access_private_node().set_extra_data(
00598 any(extra_data), name, destroy_when,
00599 force_unique );
00600 }
00601
00602
00603 template<class T1, class T2>
00604 REFCOUNTPTR_INLINE
00605 const T1& Teuchos::get_extra_data( const RCP<T2>& p, const std::string& name )
00606 {
00607 p.assert_not_null();
00608 return any_cast<T1>(
00609 p.access_private_node().get_extra_data(
00610 TypeNameTraits<T1>::name(), name
00611 )
00612 );
00613 }
00614
00615
00616 template<class T1, class T2>
00617 REFCOUNTPTR_INLINE
00618 T1& Teuchos::get_nonconst_extra_data( RCP<T2>& p, const std::string& name )
00619 {
00620 p.assert_not_null();
00621 return any_cast<T1>(
00622 p.nonconst_access_private_node().get_extra_data(
00623 TypeNameTraits<T1>::name(), name
00624 )
00625 );
00626 }
00627
00628
00629 template<class T1, class T2>
00630 REFCOUNTPTR_INLINE
00631 Teuchos::Ptr<const T1>
00632 Teuchos::get_optional_extra_data( const RCP<T2>& p, const std::string& name )
00633 {
00634 p.assert_not_null();
00635 const any *extra_data = p.access_private_node().get_optional_extra_data(
00636 TypeNameTraits<T1>::name(), name);
00637 if (extra_data)
00638 return Ptr<const T1>(&any_cast<T1>(*extra_data));
00639 return null;
00640 }
00641
00642
00643 template<class T1, class T2>
00644 REFCOUNTPTR_INLINE
00645 Teuchos::Ptr<T1>
00646 Teuchos::get_optional_nonconst_extra_data( RCP<T2>& p, const std::string& name )
00647 {
00648 p.assert_not_null();
00649 any *extra_data = p.nonconst_access_private_node().get_optional_extra_data(
00650 TypeNameTraits<T1>::name(), name);
00651 if (extra_data)
00652 return Ptr<T1>(&any_cast<T1>(*extra_data));
00653 return null;
00654 }
00655
00656
00657 template<class Dealloc_T, class T>
00658 inline
00659 const Dealloc_T& Teuchos::get_dealloc( const RCP<T>& p )
00660 {
00661 return get_nonconst_dealloc<Dealloc_T>(const_cast<RCP<T>&>(p));
00662 }
00663
00664
00665 template<class Dealloc_T, class T>
00666 REFCOUNTPTR_INLINE
00667 Dealloc_T& Teuchos::get_nonconst_dealloc( const RCP<T>& p )
00668 {
00669 typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T> requested_type;
00670 p.assert_not_null();
00671 RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>
00672 *dnode = dynamic_cast<RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T>*>(
00673 p.access_private_node().node_ptr());
00674 TEST_FOR_EXCEPTION(
00675 dnode==NULL, NullReferenceError
00676 ,"get_dealloc<" << TypeNameTraits<Dealloc_T>::name()
00677 << "," << TypeNameTraits<T>::name() << ">(p): "
00678 << "Error, requested type \'" << TypeNameTraits<requested_type>::name()
00679 << "\' does not match actual type of the node \'"
00680 << typeName(*p.access_private_node().node_ptr()) << "!"
00681 );
00682 return dnode->get_nonconst_dealloc();
00683 }
00684
00685
00686 template<class Dealloc_T, class T>
00687 REFCOUNTPTR_INLINE
00688 Teuchos::Ptr<Dealloc_T>
00689 Teuchos::get_optional_nonconst_dealloc( const RCP<T>& p )
00690 {
00691 p.assert_not_null();
00692 typedef RCPNodeTmpl<typename Dealloc_T::ptr_t,Dealloc_T> RCPNT;
00693 RCPNT *dnode = dynamic_cast<RCPNT*>(p.access_private_node().node_ptr());
00694 if(dnode)
00695 return ptr(&dnode->get_nonconst_dealloc());
00696 return null;
00697 }
00698
00699
00700 template<class Dealloc_T, class T>
00701 inline
00702 Teuchos::Ptr<const Dealloc_T>
00703 Teuchos::get_optional_dealloc( const RCP<T>& p )
00704 {
00705 return get_optional_nonconst_dealloc<Dealloc_T>(const_cast<RCP<T>&>(p));
00706 }
00707
00708
00709 template<class TOrig, class Embedded, class T>
00710 const Embedded& Teuchos::getEmbeddedObj( const RCP<T>& p )
00711 {
00712 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00713 return get_dealloc<Dealloc_t>(p).getObj();
00714 }
00715
00716
00717 template<class TOrig, class Embedded, class T>
00718 Embedded& Teuchos::getNonconstEmbeddedObj( const RCP<T>& p )
00719 {
00720 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00721 return get_nonconst_dealloc<Dealloc_t>(p).getNonconstObj();
00722 }
00723
00724
00725 template<class TOrig, class Embedded, class T>
00726 Teuchos::Ptr<const Embedded>
00727 Teuchos::getOptionalEmbeddedObj( const RCP<T>& p )
00728 {
00729 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00730 const Ptr<const Dealloc_t> dealloc = get_optional_dealloc<Dealloc_t>(p);
00731 if (!is_null(dealloc)) {
00732 return ptr(&dealloc->getObj());
00733 }
00734 return null;
00735 }
00736
00737
00738 template<class TOrig, class Embedded, class T>
00739 Teuchos::Ptr<Embedded>
00740 Teuchos::getOptionalNonconstEmbeddedObj( const RCP<T>& p )
00741 {
00742 typedef EmbeddedObjDealloc<TOrig,Embedded,DeallocDelete<TOrig> > Dealloc_t;
00743 const Ptr<Dealloc_t> dealloc = get_optional_nonconst_dealloc<Dealloc_t>(p);
00744 if (!is_null(dealloc)) {
00745 return ptr(&dealloc->getNonconstObj());
00746 }
00747 return null;
00748 }
00749
00750
00751 template<class T>
00752 std::ostream& Teuchos::operator<<( std::ostream& out, const RCP<T>& p )
00753 {
00754 out
00755 << typeName(p) << "{"
00756 << "ptr="<<(const void*)(p.get())
00757 <<",node="<<p.access_private_node()
00758 <<",count="<<p.count()
00759 <<"}";
00760 return out;
00761 }
00762
00763
00764 #endif // TEUCHOS_RCP_HPP