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