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