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