1 #ifndef MSP_CORE_REFPTR_H_
2 #define MSP_CORE_REFPTR_H_
10 KEEP = 1U<<(sizeof(unsigned)*8-1)
14 unsigned weak_count = 0;
22 A reference counting smart pointer. When the last RefPtr for the data gets
23 destroyed, the data is deleted as well.
28 template<typename U> friend class RefPtr;
29 template<typename U> friend class WeakPtr;
33 RefCounts *counts = nullptr;
37 RefPtr(T *d): data(d), counts(data ? new RefCounts : nullptr) { incref(); }
39 RefPtr(T *d, RefCounts *c): data(d), counts(d ? c : nullptr) { incref(); }
42 /* Must have this or the compiler will generate a default copy-c'tor despite
43 the template version */
44 RefPtr(const RefPtr &p): data(p.data), counts(p.counts) { incref(); }
47 RefPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
50 RefPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
52 ~RefPtr() { decref(); }
54 RefPtr &operator=(T *);
56 // Likewise for the assignment operator
57 RefPtr &operator=(const RefPtr &p) { return assign(p); }
60 RefPtr &operator=(const RefPtr<U> &p) { return assign(p); }
63 RefPtr &operator=(const WeakPtr<U> &p) { return assign(RefPtr(p)); }
67 RefPtr &assign(const RefPtr<U> &);
70 /** Makes the RefPtr release its reference of the data without deleting it.
71 Note that if there are other RefPtrs left with the same data, it might
72 still get deleted automatically. */
75 /** Marks the data to not be deleted. This affects all RefPtrs with the
77 void keep() { if(counts) counts->count |= RefCounts::KEEP; }
79 T *get() const { return data; }
80 T &operator*() const { return *data; }
81 T *operator->() const { return data; }
82 explicit operator bool() const { return data; }
84 unsigned refcount() const { return (data ? counts->count : 0); }
87 static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
88 { return RefPtr<T>(dynamic_cast<T *>(p.data), p.counts); }
91 void incref() { if(counts) ++counts->count; }
99 template<typename U> friend class RefPtr;
100 template<typename U> friend class WeakPtr;
104 RefCounts *counts = nullptr;
109 WeakPtr(T *d, RefCounts *c): data(d), counts(d ? c : nullptr) { incref(); }
112 WeakPtr(const WeakPtr &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
115 WeakPtr(const WeakPtr<U> &p): data(p.get()), counts(data ? p.counts : nullptr) { incref(); }
118 WeakPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
120 WeakPtr &operator=(const WeakPtr &p) { return assign(p); }
123 WeakPtr &operator=(const WeakPtr<U> &p) { return assign(p); }
126 WeakPtr &operator=(const RefPtr<U> &p) { return assign(WeakPtr(p)); }
130 WeakPtr &assign(const WeakPtr<U> &);
132 T *get() const { return (counts && counts->count ? data : nullptr); }
133 void incref() { if(counts) ++counts->weak_count; }
139 RefPtr<T> &RefPtr<T>::operator=(T *d)
143 counts = (d ? new RefCounts : nullptr);
150 RefPtr<T> &RefPtr<T>::assign(const RefPtr<U> &p)
152 if(static_cast<const void *>(&p)==this)
163 T *RefPtr<T>::release()
173 void RefPtr<T>::decref()
182 else if(counts->count==RefCounts::KEEP)
187 if(!counts->weak_count)
197 WeakPtr<T> &WeakPtr<T>::assign(const WeakPtr<U> &p)
204 counts = (data ? p.counts : nullptr);
210 void WeakPtr<T>::decref()
213 --counts->weak_count;
214 if(!counts->weak_count && (!counts->count || counts->count==RefCounts::KEEP))