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