-/* $Id$
-
-This file is part of libmspcore
-Copyright © 2006-2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
#ifndef MSP_CORE_REFPTR_H_
#define MSP_CORE_REFPTR_H_
template<typename T>
class RefPtr
{
+ template<typename U> friend class RefPtr;
+
+private:
+ enum
+ {
+ KEEP = 1U<<(sizeof(unsigned)*8-1)
+ };
+
+ T *data;
+ unsigned *count;
+
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) { }
+private:
+ RefPtr(T *d, unsigned *c): data(d), count(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 &operator=(const RefPtr &p)
+
+ template<typename U>
+ RefPtr(const RefPtr<U> &p): data(p.data), count(p.count) { incref(); }
+
+ ~RefPtr() { decref(); }
+
+ RefPtr &operator=(T *d)
+ {
+ decref();
+ 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); }
+
+private:
+ template<typename U>
+ RefPtr &assign(const RefPtr<U> &p)
{
decref();
- data=p.data;
- count=p.count;
+ data = p.data;
+ count = p.count;
incref();
return *this;
}
-
- ~RefPtr() { decref(); }
- /**
- Makes the RefPtr release its reference of the data. Note that if there are
- other RefPtrs left with the same data, it might still get deleted
- automatically.
- */
+public:
+ /** Makes the RefPtr release its reference of the data without deleting it.
+ Note that if there are other RefPtrs left with the same data, it might
+ still get deleted automatically. */
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); }
- template<typename U> friend class RefPtr;
-private:
- T *data;
- unsigned *count;
+ static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
+ { return RefPtr<T>(dynamic_cast<T *>(p.data), p.count); }
- RefPtr(T *d, unsigned *c): data(d), count(c) { incref(); }
-
- void incref()
+private:
+ 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;
}
}
};