Move RefPtr refcount into a struct
authorMikko Rasa <tdb@tdb.fi>
Sat, 6 Feb 2021 09:51:17 +0000 (11:51 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 6 Feb 2021 09:51:17 +0000 (11:51 +0200)
This is necessary to implement weak pointers

source/core/refptr.h

index 0328340eb242242b29fa614d0b7b815eddcc8f3b..8ab1b7cbfbdb6e752afd4b7634e807a8a836e10a 100644 (file)
@@ -3,6 +3,19 @@
 
 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.
@@ -13,27 +26,22 @@ class RefPtr
        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(); }
 
@@ -41,7 +49,8 @@ public:
        {
                decref();
                data = d;
-               count = (d ? new unsigned(1) : 0);
+               counts = (d ? new RefCounts : 0);
+               incref();
                return *this;
        }
 
@@ -57,7 +66,7 @@ private:
        {
                decref();
                data = p.data;
-               count = p.count;
+               counts = p.counts;
                incref();
                return *this;
        }
@@ -71,7 +80,7 @@ public:
                T *d = data;
                data = 0;
                decref();
-               count = 0;
+               counts = 0;
                return d;
        }
 
@@ -79,8 +88,8 @@ public:
        same data. */
        void keep()
        {
-               if(count)
-                       *count |= KEEP;
+               if(counts)
+                       counts->count |= RefCounts::KEEP;
        }
 
        T *get() const { return data; }
@@ -88,35 +97,35 @@ public:
        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;
                }
        }
 };