1 #ifndef MSP_CORE_REFPTR_H_
2 #define MSP_CORE_REFPTR_H_
10 KEEP = 1U<<(sizeof(unsigned)*8-1)
16 RefCounts(): count(0), weak_count(0) { }
24 A reference counting smart pointer. When the last RefPtr for the data gets
25 destroyed, the data is deleted as well.
30 template<typename U> friend class RefPtr;
31 template<typename U> friend class WeakPtr;
38 RefPtr(): data(0), counts(0) { }
39 RefPtr(T *d): data(d), counts(data ? new RefCounts : 0) { incref(); }
41 RefPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
44 /* Must have this or the compiler will generate a default copy-c'tor despite
45 the template version */
46 RefPtr(const RefPtr &p): data(p.data), counts(p.counts) { incref(); }
49 RefPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
52 RefPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
54 ~RefPtr() { decref(); }
56 RefPtr &operator=(T *);
58 // Likewise for the assignment operator
59 RefPtr &operator=(const RefPtr &p) { return assign(p); }
62 RefPtr &operator=(const RefPtr<U> &p) { return assign(p); }
65 RefPtr &operator=(const WeakPtr<U> &p) { return assign(RefPtr(p)); }
69 RefPtr &assign(const RefPtr<U> &);
72 /** Makes the RefPtr release its reference of the data without deleting it.
73 Note that if there are other RefPtrs left with the same data, it might
74 still get deleted automatically. */
77 /** Marks the data to not be deleted. This affects all RefPtrs with the
79 void keep() { if(counts) counts->count |= RefCounts::KEEP; }
81 T *get() const { return data; }
82 T &operator*() const { return *data; }
83 T *operator->() const { return data; }
84 operator bool() const { return data!=0; }
86 unsigned refcount() const { return (data ? counts->count : 0); }
89 static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
90 { return RefPtr<T>(dynamic_cast<T *>(p.data), p.counts); }
93 void incref() { if(counts) ++counts->count; }
101 template<typename U> friend class RefPtr;
102 template<typename U> friend class WeakPtr;
109 WeakPtr(): data(0), counts(0) { }
111 WeakPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
114 WeakPtr(const WeakPtr &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
117 WeakPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : 0) { incref(); }
120 WeakPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
122 WeakPtr &operator=(const WeakPtr &p) { return assign(p); }
125 WeakPtr &operator=(const WeakPtr<U> &p) { return assign(p); }
128 WeakPtr &operator=(const RefPtr<U> &p) { return assign(WeakPtr(p)); }
132 WeakPtr &assign(const WeakPtr<U> &);
134 T *get() const { return (counts && counts->count ? data : 0); }
135 void incref() { if(counts) ++counts->weak_count; }
141 RefPtr<T> &RefPtr<T>::operator=(T *d)
145 counts = (d ? new RefCounts : 0);
152 RefPtr<T> &RefPtr<T>::assign(const RefPtr<U> &p)
162 T *RefPtr<T>::release()
172 void RefPtr<T>::decref()
181 else if(counts->count==RefCounts::KEEP)
186 if(!counts->weak_count)
196 WeakPtr<T> &WeakPtr<T>::assign(const WeakPtr<U> &p)
200 counts = (data ? p.counts : 0);
206 void WeakPtr<T>::decref()
209 --counts->weak_count;
210 if(!counts->weak_count && (!counts->count || counts->count==RefCounts::KEEP))