ViennaCL - The Vienna Computing Library  1.5.2
viennacl/tools/shared_ptr.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_TOOLS_SHARED_PTR_HPP
00002 #define VIENNACL_TOOLS_SHARED_PTR_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2012, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00027 #include <cstdlib>
00028 #include <algorithm>
00029 
00030 namespace viennacl
00031 {
00032   namespace tools
00033   {
00034 
00035     namespace detail
00036     {
00037 
00039       class count
00040       {
00041         public:
00042           count(unsigned int val) : val_(val){ }
00043           void dec(){ --val_; }
00044           void inc(){ ++val_; }
00045           bool is_null(){ return val_ == 0; }
00046           unsigned int val(){ return val_; }
00047         private:
00048           unsigned int val_;
00049       };
00050 
00052       struct aux
00053       {
00054         detail::count count;
00055 
00056         aux() :count(1) {}
00057         virtual void destroy()=0;
00058         virtual ~aux() {}
00059       };
00060 
00062       template<class U, class Deleter>
00063       struct auximpl: public detail::aux
00064       {
00065         U* p;
00066         Deleter d;
00067 
00068         auximpl(U* pu, Deleter x) :p(pu), d(x) {}
00069         virtual void destroy() { d(p); }
00070       };
00071 
00073       template<class U>
00074       struct default_deleter
00075       {
00076         void operator()(U* p) const { delete p; }
00077       };
00078 
00079     }
00080 
00082     template<class T>
00083     class shared_ptr
00084     {
00085         template<class U>
00086         friend class shared_ptr;
00087 
00088         detail::aux* pa;
00089         T* pt;
00090 
00091       public:
00092 
00093         shared_ptr() :pa(NULL), pt(NULL) {}
00094 
00095         template<class U, class Deleter>
00096         shared_ptr(U* pu, Deleter d) : pa(new detail::auximpl<U, Deleter>(pu, d)), pt(pu) {}
00097 
00098         template<class U>
00099         explicit shared_ptr(U* pu) : pa(new detail::auximpl<U, detail::default_deleter<U> >(pu, detail::default_deleter<U>())), pt(pu) {}
00100 
00101         shared_ptr(const shared_ptr& s) :pa(s.pa), pt(s.pt) { inc(); }
00102 
00103         template<class U>
00104         shared_ptr(const shared_ptr<U>& s) :pa(s.pa), pt(s.pt) { inc(); }
00105 
00106         ~shared_ptr() { dec(); }
00107 
00108         void reset(){
00109             shared_ptr<T>().swap(*this);
00110         }
00111 
00112         void reset(T * ptr){
00113             shared_ptr<T>(ptr).swap(*this);
00114         }
00115 
00116         void swap(shared_ptr<T> & other){
00117             std::swap(pt,other.pt);
00118             std::swap(pa, other.pa);
00119         }
00120 
00121 
00122         shared_ptr& operator=(const shared_ptr& s)
00123         {
00124             if(this!=&s)
00125             {
00126                 dec();
00127                 pa = s.pa;
00128                 pt = s.pt;
00129                 inc();
00130             }
00131             return *this;
00132         }
00133 
00134         T* get() const {  return pt; }
00135 
00136         T* operator->() const {  return pt; }
00137 
00138         T& operator*() const { return *pt; }
00139 
00140         void inc() { if(pa) pa->count.inc(); }
00141 
00142         void dec()
00143         {
00144           if(pa)
00145           {
00146             pa->count.dec();
00147 
00148             if(pa->count.is_null())
00149             {
00150                 pa->destroy();
00151                 delete pa;
00152                 pa = NULL;
00153             }
00154           }
00155         }
00156 
00157     };
00158 
00159   }
00160 
00161 }
00162 
00163 #endif // VIENNACL_UTILS_SHARED_PTR_HPP