/* $Id$
This file is part of libmspcore
-Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2007, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
template<typename T>
class RefPtr
{
+private:
+ enum
+ {
+ KEEP = 1U<<(sizeof(unsigned)*8-1)
+ };
+
public:
RefPtr(): data(0), count(0) { }
- RefPtr(T *d): data(d), count(0) { if(data) count=new unsigned(1); }
+ RefPtr(T *d): data(d), count(data ? new unsigned(1) : 0) { }
+
+ // Must have this or the compiler will generate a default copy-c'tor
RefPtr(const RefPtr &p): data(p.data), count(p.count) { incref(); }
- RefPtr &operator=(const RefPtr &p)
+
+ template<typename U>
+ RefPtr(const RefPtr<U> &p): data(p.data), count(p.count) { incref(); }
+
+ RefPtr &operator=(T *d)
{
decref();
- data=p.data;
- count=p.count;
- incref();
+ data = d;
+ count = (d ? new unsigned(1) : 0);
return *this;
}
+
+ // Likewise for the assignment operator
+ RefPtr &operator=(const RefPtr &p) { return assign(p); }
+
+ template<typename U>
+ RefPtr &operator=(const RefPtr<U> &p) { return assign(p); }
~RefPtr() { decref(); }
*/
T *release()
{
- T *d=data;
- data=0;
+ T *d = data;
+ data = 0;
decref();
- count=0;
+ count = 0;
return d;
}
- T *get() const { return data; }
- T &operator*() const { return *data; }
+ /**
+ Marks the data to not be deleted. This affects all RefPtrs with the same
+ data.
+ */
+ void keep()
+ {
+ if(count)
+ *count |= KEEP;
+ }
+
+ T *get() const { return data; }
+ T &operator*() const { return *data; }
T *operator->() const { return data; }
operator bool() const { return data!=0; }
template<typename U>
- static RefPtr<T> cast_dynamic(const RefPtr<U> &p) { return RefPtr<T>(dynamic_cast<T *>(p.data), p.count); }
+ static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
+ { return RefPtr<T>(dynamic_cast<T *>(p.data), p.count); }
+
template<typename U> friend class RefPtr;
private:
- T *data;
+ T *data;
unsigned *count;
- RefPtr(T *d, unsigned *c): data(d), count(c) { incref(); }
+ RefPtr(T *d, unsigned *c): data(d), count(d ? c : 0) { incref(); }
- void incref()
+ template<typename U>
+ RefPtr &assign(const RefPtr<U> &p)
+ {
+ decref();
+ data = p.data;
+ count = p.count;
+ incref();
+ return *this;
+ }
+
+ void incref()
{
if(!count) return;
++*count;
}
- void decref()
+ void decref()
{
if(!count) return;
--*count;
{
delete data;
delete count;
- data=0;
- count=0;
+ data = 0;
+ count = 0;
+ }
+ else if(*count==KEEP)
+ {
+ delete count;
+ data = 0;
+ count = 0;
}
}
};