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