]> git.tdb.fi Git - libs/core.git/blob - source/core/refptr.h
20450f1b412462e60d10c92b0de7c72b858c6cca
[libs/core.git] / source / core / refptr.h
1 /* $Id$
2
3 This file is part of libmspcore
4 Copyright © 2006-2007, 2010-2011 Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_CORE_REFPTR_H_
9 #define MSP_CORE_REFPTR_H_
10
11 namespace Msp {
12
13 /**
14 A reference counting smart pointer.  When the last RefPtr for the data gets
15 destroyed, the data is deleted as well.
16 */
17 template<typename T>
18 class RefPtr
19 {
20         template<typename U> friend class RefPtr;
21
22 private:
23         enum
24         {
25                 KEEP = 1U<<(sizeof(unsigned)*8-1)
26         };
27
28         T *data;
29         unsigned *count;
30
31 public:
32         RefPtr(): data(0), count(0) { }
33         RefPtr(T *d): data(d), count(data ? new unsigned(1) : 0) { }
34 private:
35         RefPtr(T *d, unsigned *c): data(d), count(d ? c : 0) { incref(); }
36
37 public:
38         /* Must have this or the compiler will generate a default copy-c'tor despite
39         the template version */
40         RefPtr(const RefPtr &p): data(p.data), count(p.count) { incref(); }
41
42         template<typename U>
43         RefPtr(const RefPtr<U> &p): data(p.data), count(p.count) { incref(); }
44
45         ~RefPtr() { decref(); }
46
47         RefPtr &operator=(T *d)
48         {
49                 decref();
50                 data = d;
51                 count = (d ? new unsigned(1) : 0);
52                 return *this;
53         }
54
55         // Likewise for the assignment operator
56         RefPtr &operator=(const RefPtr &p) { return assign(p); }
57
58         template<typename U>
59         RefPtr &operator=(const RefPtr<U> &p) { return assign(p); }
60
61 private:
62         template<typename U>
63         RefPtr &assign(const RefPtr<U> &p)
64         {
65                 decref();
66                 data = p.data;
67                 count = p.count;
68                 incref();
69                 return *this;
70         }
71
72 public:
73         /** Makes the RefPtr release its reference of the data without deleting it.
74         Note that if there are other RefPtrs left with the same data, it might
75         still get deleted automatically. */
76         T *release()
77         {
78                 T *d = data;
79                 data = 0;
80                 decref();
81                 count = 0;
82                 return d;
83         }
84
85         /** Marks the data to not be deleted.  This affects all RefPtrs with the
86         same data. */
87         void keep()
88         {
89                 if(count)
90                         *count |= KEEP;
91         }
92
93         T *get() const { return data; }
94         T &operator*() const { return *data; }
95         T *operator->() const { return data; }
96         operator bool() const { return data!=0; }
97
98         template<typename U>
99         static RefPtr<T> cast_dynamic(const RefPtr<U> &p)
100         { return RefPtr<T>(dynamic_cast<T *>(p.data), p.count); }
101
102 private:
103         void incref()
104         {
105                 if(!count) return;
106                 ++*count;
107         }
108
109         void decref()
110         {
111                 if(!count) return;
112                 --*count;
113                 if(!*count)
114                 {
115                         delete data;
116                         delete count;
117                         data = 0;
118                         count = 0;
119                 }
120                 else if(*count==KEEP)
121                 {
122                         delete count;
123                         data = 0;
124                         count = 0;
125                 }
126         }
127 };
128
129 } // namespace Msp
130
131 #endif