};
unsigned count;
+ unsigned weak_count;
- RefCounts(): count(0) { }
+ RefCounts(): count(0), weak_count(0) { }
};
+template<typename T>
+class WeakPtr;
+
/**
A reference counting smart pointer. When the last RefPtr for the data gets
class RefPtr
{
template<typename U> friend class RefPtr;
+ template<typename U> friend class WeakPtr;
private:
T *data;
template<typename U>
RefPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
+ template<typename U>
+ RefPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+
~RefPtr() { decref(); }
RefPtr &operator=(T *);
template<typename U>
RefPtr &operator=(const RefPtr<U> &p) { return assign(p); }
+ template<typename U>
+ RefPtr &operator=(const WeakPtr<U> &p) { return assign(RefPtr(p)); }
+
private:
template<typename U>
RefPtr &assign(const RefPtr<U> &);
};
+template<typename T>
+class WeakPtr
+{
+ template<typename U> friend class RefPtr;
+ template<typename U> friend class WeakPtr;
+
+private:
+ T *data;
+ RefCounts *counts;
+
+public:
+ WeakPtr(): data(0), counts(0) { }
+private:
+ WeakPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
+
+public:
+ WeakPtr(const WeakPtr &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+
+ template<typename U>
+ WeakPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
+
+ template<typename U>
+ WeakPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
+
+ WeakPtr &operator=(const WeakPtr &p) { return assign(p); }
+
+ template<typename U>
+ WeakPtr &operator=(const WeakPtr<U> &p) { return assign(p); }
+
+ template<typename U>
+ WeakPtr &operator=(const RefPtr<U> &p) { return assign(WeakPtr(p)); }
+
+private:
+ template<typename U>
+ WeakPtr &assign(const WeakPtr<U> &);
+
+ T *get() const { return (counts && counts->count ? data : 0); }
+ void incref() { if(counts) ++counts->weak_count; }
+ void decref();
+};
+
+
template<typename T>
RefPtr<T> &RefPtr<T>::operator=(T *d)
{
if(!counts->count)
{
delete data;
- delete counts;
data = 0;
- counts = 0;
}
else if(counts->count==RefCounts::KEEP)
+ data = 0;
+ else
+ return;
+
+ if(!counts->weak_count)
+ {
+ delete counts;
+ counts = 0;
+ }
+}
+
+
+template<typename T>
+template<typename U>
+WeakPtr<T> &WeakPtr<T>::assign(const WeakPtr<U> &p)
+{
+ decref();
+ data = p.get();
+ counts = (data ? p.counts : 0);
+ incref();
+ return *this;
+}
+
+template<typename T>
+void WeakPtr<T>::decref()
+{
+ if(!counts) return;
+ --counts->weak_count;
+ if(!counts->weak_count && (!counts->count || counts->count==RefCounts::KEEP))
{
delete counts;
data = 0;