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