namespace Msp {
+struct RefCounts
+{
+ enum
+ {
+ KEEP = 1U<<(sizeof(unsigned)*8-1)
+ };
+
+ unsigned count;
+
+ RefCounts(): count(0) { }
+};
+
+
/**
A reference counting smart pointer. When the last RefPtr for the data gets
destroyed, the data is deleted as well.
template<typename U> friend class RefPtr;
private:
- enum
- {
- KEEP = 1U<<(sizeof(unsigned)*8-1)
- };
-
T *data;
- unsigned *count;
+ RefCounts *counts;
public:
- RefPtr(): data(0), count(0) { }
- RefPtr(T *d): data(d), count(data ? new unsigned(1) : 0) { }
+ RefPtr(): data(0), counts(0) { }
+ RefPtr(T *d): data(d), counts(data ? new RefCounts : 0) { incref(); }
private:
- RefPtr(T *d, unsigned *c): data(d), count(d ? c : 0) { incref(); }
+ RefPtr(T *d, RefCounts *c): data(d), counts(d ? c : 0) { incref(); }
public:
/* Must have this or the compiler will generate a default copy-c'tor despite
the template version */
- RefPtr(const RefPtr &p): data(p.data), count(p.count) { incref(); }
+ RefPtr(const RefPtr &p): data(p.data), counts(p.counts) { incref(); }
template<typename U>
- RefPtr(const RefPtr<U> &p): data(p.data), count(p.count) { incref(); }
+ RefPtr(const RefPtr<U> &p): data(p.data), counts(p.counts) { incref(); }
~RefPtr() { decref(); }
{
decref();
data = d;
- count = (d ? new unsigned(1) : 0);
+ counts = (d ? new RefCounts : 0);
+ incref();
return *this;
}
{
decref();
data = p.data;
- count = p.count;
+ counts = p.counts;
incref();
return *this;
}
T *d = data;
data = 0;
decref();
- count = 0;
+ counts = 0;
return d;
}
same data. */
void keep()
{
- if(count)
- *count |= KEEP;
+ if(counts)
+ counts->count |= RefCounts::KEEP;
}
T *get() const { return data; }
T *operator->() const { return data; }
operator bool() const { return data!=0; }
- unsigned refcount() const { return (data ? *count : 0); }
+ unsigned refcount() const { return (data ? counts->count : 0); }
template<typename U>
static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
- { return RefPtr<T>(dynamic_cast<T *>(p.data), p.count); }
+ { return RefPtr<T>(dynamic_cast<T *>(p.data), p.counts); }
private:
void incref()
{
- if(!count) return;
- ++*count;
+ if(!counts) return;
+ ++counts->count;
}
void decref()
{
- if(!count) return;
- --*count;
- if(!*count)
+ if(!counts) return;
+ --counts->count;
+ if(!counts->count)
{
delete data;
- delete count;
+ delete counts;
data = 0;
- count = 0;
+ counts = 0;
}
- else if(*count==KEEP)
+ else if(counts->count==RefCounts::KEEP)
{
- delete count;
+ delete counts;
data = 0;
- count = 0;
+ counts = 0;
}
}
};