diff options
Diffstat (limited to 'src/FbTk/RefCount.hh')
-rw-r--r-- | src/FbTk/RefCount.hh | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/src/FbTk/RefCount.hh b/src/FbTk/RefCount.hh index ba2a697..ab4c663 100644 --- a/src/FbTk/RefCount.hh +++ b/src/FbTk/RefCount.hh | |||
@@ -25,6 +25,7 @@ | |||
25 | namespace FbTk { | 25 | namespace FbTk { |
26 | 26 | ||
27 | /// holds a pointer with reference counting, similar to std:auto_ptr | 27 | /// holds a pointer with reference counting, similar to std:auto_ptr |
28 | |||
28 | template <typename Pointer> | 29 | template <typename Pointer> |
29 | class RefCount { | 30 | class RefCount { |
30 | public: | 31 | public: |
@@ -43,37 +44,47 @@ public: | |||
43 | unsigned int usedBy() const { return (m_refcount != 0 ? *m_refcount : 0); } | 44 | unsigned int usedBy() const { return (m_refcount != 0 ? *m_refcount : 0); } |
44 | #endif | 45 | #endif |
45 | private: | 46 | private: |
46 | /// increase referense count | 47 | /// increase reference count |
47 | void incRefCount(); | 48 | void incRefCount(); |
48 | /// decrease referense count | 49 | /// decrease reference count |
49 | void decRefCount(); | 50 | void decRefCount(); |
51 | /// decrease refcount count | ||
52 | void decRefCountCount(); | ||
50 | Pointer *m_data; ///< data holder | 53 | Pointer *m_data; ///< data holder |
51 | mutable unsigned int *m_refcount; ///< holds reference counting | 54 | mutable unsigned int *m_refcount; ///< holds reference counting |
55 | |||
56 | // This one counts the number of active references pointing to the m_refcount data! | ||
57 | // when it reaches zero, *then* we can delete it, otherwise someone else might check it. | ||
58 | mutable unsigned int *m_refcount_count; ///< holds reference counting | ||
52 | }; | 59 | }; |
53 | 60 | ||
54 | // implementation | 61 | // implementation |
55 | 62 | ||
56 | template <typename Pointer> | 63 | template <typename Pointer> |
57 | RefCount<Pointer>::RefCount():m_data(0), m_refcount(new unsigned int(0)) { | 64 | RefCount<Pointer>::RefCount():m_data(0), m_refcount(new unsigned int(0)), m_refcount_count(new unsigned int(1)) { |
58 | 65 | ||
59 | } | 66 | } |
60 | 67 | ||
61 | template <typename Pointer> | 68 | template <typename Pointer> |
62 | RefCount<Pointer>::RefCount(RefCount<Pointer> ©): | 69 | RefCount<Pointer>::RefCount(RefCount<Pointer> ©): |
63 | m_data(copy.m_data), | 70 | m_data(copy.m_data), |
64 | m_refcount(copy.m_refcount) { | 71 | m_refcount(copy.m_refcount), |
72 | m_refcount_count(copy.m_refcount_count) { | ||
73 | (*m_refcount_count)++; | ||
65 | incRefCount(); | 74 | incRefCount(); |
66 | } | 75 | } |
67 | 76 | ||
68 | template <typename Pointer> | 77 | template <typename Pointer> |
69 | RefCount<Pointer>::RefCount(Pointer *p):m_data(p), m_refcount(new unsigned int(0)) { | 78 | RefCount<Pointer>::RefCount(Pointer *p):m_data(p), m_refcount(new unsigned int(0)), m_refcount_count(new unsigned int(1)) { |
70 | incRefCount(); | 79 | incRefCount(); |
71 | } | 80 | } |
72 | 81 | ||
73 | template <typename Pointer> | 82 | template <typename Pointer> |
74 | RefCount<Pointer>::RefCount(const RefCount<Pointer> ©): | 83 | RefCount<Pointer>::RefCount(const RefCount<Pointer> ©): |
75 | m_data(copy.m_data), | 84 | m_data(copy.m_data), |
76 | m_refcount(copy.m_refcount) { | 85 | m_refcount(copy.m_refcount), |
86 | m_refcount_count(copy.m_refcount_count) { | ||
87 | (*m_refcount_count)++; | ||
77 | incRefCount(); | 88 | incRefCount(); |
78 | } | 89 | } |
79 | 90 | ||
@@ -86,6 +97,8 @@ template <typename Pointer> | |||
86 | RefCount<Pointer> &RefCount<Pointer>::operator = (const RefCount<Pointer> ©) { | 97 | RefCount<Pointer> &RefCount<Pointer>::operator = (const RefCount<Pointer> ©) { |
87 | decRefCount(); // dec current ref count | 98 | decRefCount(); // dec current ref count |
88 | m_refcount = copy.m_refcount; // set new ref count | 99 | m_refcount = copy.m_refcount; // set new ref count |
100 | m_refcount_count = copy.m_refcount_count; | ||
101 | (*m_refcount_count)++; | ||
89 | m_data = copy.m_data; // set new data pointer | 102 | m_data = copy.m_data; // set new data pointer |
90 | incRefCount(); // inc new ref count | 103 | incRefCount(); // inc new ref count |
91 | return *this; | 104 | return *this; |
@@ -96,27 +109,35 @@ RefCount<Pointer> &RefCount<Pointer>::operator = (Pointer *p) { | |||
96 | decRefCount(); | 109 | decRefCount(); |
97 | m_data = p; // set data pointer | 110 | m_data = p; // set data pointer |
98 | m_refcount = new unsigned int(0); // create new counter | 111 | m_refcount = new unsigned int(0); // create new counter |
112 | m_refcount_count = new unsigned int(1); | ||
99 | incRefCount(); | 113 | incRefCount(); |
100 | return *this; | 114 | return *this; |
101 | } | 115 | } |
102 | 116 | ||
103 | template <typename Pointer> | 117 | template <typename Pointer> |
104 | void RefCount<Pointer>::decRefCount() { | 118 | void RefCount<Pointer>::decRefCount() { |
105 | if (m_refcount == 0) | 119 | if (m_refcount != 0) { |
106 | return; | 120 | (*m_refcount)--; |
107 | if (*m_refcount == 0) { // already zero, then delete refcount | 121 | if (*m_refcount == 0) { // destroy m_data and m_refcount if nobody else is using this |
108 | delete m_refcount; | 122 | if (m_data != 0) |
109 | m_refcount = 0; | 123 | delete m_data; |
110 | return; | 124 | m_data = 0; |
125 | } | ||
111 | } | 126 | } |
112 | (*m_refcount)--; | 127 | decRefCountCount(); |
113 | if (*m_refcount == 0) { // destroy m_data and m_refcount if nobody else is using this | 128 | } |
114 | if (m_data != 0) | 129 | |
115 | delete m_data; | 130 | template <typename Pointer> |
116 | m_data = 0; | 131 | void RefCount<Pointer>::decRefCountCount() { |
132 | if (*m_refcount_count == 0) | ||
133 | return; // shouldnt happen | ||
134 | (*m_refcount_count)--; | ||
135 | if (*m_refcount_count == 0) { | ||
117 | delete m_refcount; | 136 | delete m_refcount; |
118 | m_refcount = 0; | 137 | delete m_refcount_count; |
119 | } | 138 | } |
139 | m_refcount = 0; | ||
140 | m_refcount_count = 0; | ||
120 | } | 141 | } |
121 | 142 | ||
122 | template <typename Pointer> | 143 | template <typename Pointer> |