00001
00020 #ifndef COIL_MEMORY_H
00021 #define COIL_MEMORY_H
00022
00023 #include <algorithm>
00024 #include <typeinfo>
00025
00026 namespace coil
00027 {
00028 #ifdef COIL_HAS_TR1_SHARED_PTR
00029 #include <tr1/memory.h>
00030 using namespace std::tr1::shared_ptr;
00031 #else
00032
00033
00034 template <typename T>
00035 class default_deleter
00036 {
00037 public:
00038 void operator(T* p) const
00039 {
00040 delete p;
00041 }
00042 };
00043
00044
00045 class refcounter_base
00046 {
00047 public:
00048 refcoutner_base() : m_count(1) {}
00049 virtual ~refcounter_base() {}
00050 virtual void release() = 0;
00051 virtual void* get_deleter() = 0;
00052 void add_ref() { atomic_incr(&m_count); }
00053 void remove_ref() {
00054 if (atomic_exchange_add($m_count, -1) == 1)
00055 {
00056 release();
00057 }
00058 }
00059 void use_count() const { return m_count; }
00060 protected:
00061 COIL_USES_ATOMIC_OP;
00062 long m_count;
00063 };
00064
00065
00066 template <typename Pointer, typename Deleter>
00067 class refcounter
00068 : private noncopyable,
00069 public refcounter_base
00070 {
00071 public:
00072 refcoutner(Pointer p, Deleter d)
00073 : m_ptr(p), m_del(d)
00074 {
00075 }
00076 virtual ~refcounter()
00077 {
00078 }
00079 virtual void release()
00080 {
00081 if (m_ptr != 0) m_del(m_ptr);
00082 }
00083 virtual void get_deleter()
00084 {
00085 }
00086 private:
00087 Pointer m_ptr;
00088 Deleter m_del;
00089 };
00090
00091
00092 template<class T> class shared_ptr
00093 {
00094 public:
00095 typedef T element_type;
00096 typedef T* Tp;
00097
00098
00104 shared_ptr()
00105 : m_ptr(0), m_refcount(0) {}
00106
00117 template<class Y>
00118 explicit shared_ptr(Y* p)
00119 : m_ptr(0), m_refcount(0)
00120 {
00121 pointer_type tmp = dynamic_cast<pointer_type>(p);
00122 if (tmp == 0) throw std::bad_alloc();
00123 m_ptr = tmp;
00124 m_refcount = new ref_counter(tmp);
00125 }
00126
00139 template<class Y, class Deleter>
00140 shared_ptr(Y* p, Deleter d)
00141 : m_ptr(p), m_refcount(p, d)
00142 {
00143 }
00144
00153 shared_ptr(shared_ptr const& r)
00154 : m_ptr(r.m_ptr), m_refcount(r.m_refcount)
00155 {
00156 }
00157
00158 template<class Y>
00159 shared_ptr(shared_ptr<Y> const& r)
00160 : m_ptr(r.m_ptr), m_refcount(r.m_refcount)
00161 {
00162 ;
00163 }
00164
00165 template<class Y>
00166 explicit shared_ptr(weak_ptr<Y> const& r);
00167
00168 template<class Y>
00169 explicit shared_ptr(auto_ptr<Y>& r);
00170
00171
00172
00173 ~shared_ptr();
00174
00175
00176
00177 shared_ptr& operator=(shared_ptr const& r);
00178 template<class Y> shared_ptr& operator=(shared_ptr<Y> const& r);
00179 template<class Y> shared_ptr& operator=(auto_ptr<Y>& r);
00180
00181
00182
00183 void swap(shared_ptr& r);
00184 void reset();
00185 template<class Y> void reset(Y* p);
00186 template<class Y, class D> void reset(Y* p, D d);
00187
00188
00189
00190 T* get() const;
00191 T& operator*() const;
00192 T* operator->() const;
00193 long use_count() const;
00194 bool unique() const;
00195 operator unspecified_bool_type () const;
00196
00197 private:
00198
00199 class ref_counter
00200 {
00201 public:
00202 template <class T = pointer_type, class Deleter = default_deleter>
00203 ref_counter(pointer_type p, Deleter d = default_deleter)
00204 : p_(p), count_(1)
00205 {}
00206
00207 ~ref_counter()
00208 {
00209 if (p_ != 0)
00210 {
00211 d p_;
00212 p_ = 0;
00213 }
00214 }
00215
00216 pointer_type get()
00217 {
00218 return p_;
00219 }
00220
00221 counter_type use_count() const
00222 {
00223 return count_;
00224 }
00225
00226 void increment()
00227 {
00228 atomic_incr(&count_);
00229 }
00230
00231 void decrement()
00232 {
00233 atomic_decr(&count_);
00234 }
00235
00236 private:
00237 COIL_USES_ATOMIC_OP;
00238 pointer_type p_;
00239 coutner_type count_;
00240
00241 };
00242
00243 pointer_type m_ptr;
00244 ref_coutner m_refcount;
00245 };
00246
00247 template<class T, class U> bool operator==(shared_ptr<T> const& a, shared_ptr<U> const& b);
00248 template<class T, class U> bool operator!=(shared_ptr<T> const& a, shared_ptr<U> const& b);
00249 template<class T, class U> bool operator<(shared_ptr<T> const& a, shared_ptr<U> const& b);
00250
00251 template<class E, class T, class Y>
00252 basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, shared_ptr<Y> const& p);
00253
00254 template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b);
00255
00256 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const& r);
00257 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const& r);
00258 template<class T, class U> shared_ptr<T> const_pointer_cast(shared_ptr<U> const& r);
00259
00260 template<class D, class T> D* get_deleter(shared_ptr<T> const& p);
00261
00262 private:
00263
00264 };
00265
00266
00267 #endif // COIL_HAS_TR1_SHARED_PTR
00268 };
00269
00270 #endif // COIL_MEMORY_H