Teuchos_RefCountPtr.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
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 // Inline implementations below, not for the client to look at.
00045 
00046 namespace Teuchos {
00047 
00048 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00049 
00050 namespace PrivateUtilityPack {
00051 
00052 // Assert that the pointer is not null
00053 void throw_null( const std::string &type_name );
00054 
00055 // Node class to keep track of the delete address and
00056 // the reference count for RefCountPtr<...>
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   // This is made a pointer to reduce overhead for the general case
00092   // where this is not used
00093   RefCountPtr_node();
00094   RefCountPtr_node(const RefCountPtr_node&);
00095   RefCountPtr_node& operator=(const RefCountPtr_node&);
00096 };  // end class RefCountPtr_node;
00097 
00098 // Implementation class for actually deleting the object if has_ownership() == true.
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   // not defined and not to be called
00122   RefCountPtr_node_tmpl();
00123   RefCountPtr_node_tmpl(const RefCountPtr_node_tmpl&);
00124   RefCountPtr_node_tmpl& operator=(const RefCountPtr_node_tmpl&);
00125 
00126 }; // end class RefCountPtr_node_tmpl<T>
00127 
00128 } // end namespace PrivateUtilityPack 
00129 
00130 #endif
00131 
00132 // /////////////////////////////////////////////////////////////////////////////////
00133 // Inline member functions for RefCountPtr<...>.
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()))                 // will not compile if T1 is not an ancestor of T2
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; // Assignment to self!
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 // private
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 // very bad public functions
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 } // end namespace Teuchos
00289 
00290 // /////////////////////////////////////////////////////////////////////////////////
00291 // Inline member functions for conversions for RefCountPtr<...>.
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(); // Make the compiler check if the conversion is legal
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()); // Make the compiler check if the conversion is legal
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()); // Make the compiler check if the conversion is legal
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; // NULL by default
00360   if( p1.get() ) {
00361     T2 *check = dynamic_cast<T2*>(p1.get()); // Make the compiler check if the conversion is legal
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); // Assert not NULL
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; // Assert not NULL
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; // Assert not NULL
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; // Assert not NULL
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

Generated on Thu Sep 18 12:42:50 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1