1 | /* |
2 | * The contents of this file are subject to the Initial |
3 | * Developer's Public License Version 1.0 (the "License"); |
4 | * you may not use this file except in compliance with the |
5 | * License. You may obtain a copy of the License at |
6 | * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl. |
7 | * |
8 | * Software distributed under the License is distributed AS IS, |
9 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. |
10 | * See the License for the specific language governing rights |
11 | * and limitations under the License. |
12 | * |
13 | * The Original Code was created by Vlad Horsun |
14 | * for the Firebird Open Source RDBMS project. |
15 | * |
16 | * Copyright (c) 2008 Vlad Horsun <hvlad@users.sf.net> |
17 | * and all contributors signed below. |
18 | * |
19 | * All Rights Reserved. |
20 | * Contributor(s): ______________________________________. |
21 | * |
22 | * Dmitry Yemanov <dimitr@users.sf.net> |
23 | */ |
24 | |
25 | #ifndef COMMON_REF_COUNTED_H |
26 | #define COMMON_REF_COUNTED_H |
27 | |
28 | #include "../common/classes/fb_atomic.h" |
29 | #include "../common/gdsassert.h" |
30 | |
31 | namespace Firebird |
32 | { |
33 | class RefCounted |
34 | { |
35 | public: |
36 | virtual int addRef() |
37 | { |
38 | return ++m_refCnt; |
39 | } |
40 | |
41 | virtual int release() |
42 | { |
43 | fb_assert(m_refCnt.value() > 0); |
44 | const int refCnt = --m_refCnt; |
45 | if (!refCnt) |
46 | delete this; |
47 | return refCnt; |
48 | } |
49 | |
50 | protected: |
51 | RefCounted() : m_refCnt(0) {} |
52 | |
53 | virtual ~RefCounted() |
54 | { |
55 | fb_assert(m_refCnt.value() == 0); |
56 | } |
57 | |
58 | private: |
59 | AtomicCounter m_refCnt; |
60 | }; |
61 | |
62 | // reference counted object guard |
63 | class Reference |
64 | { |
65 | public: |
66 | explicit Reference(RefCounted& refCounted) : |
67 | r(refCounted) |
68 | { |
69 | r.addRef(); |
70 | } |
71 | |
72 | ~Reference() |
73 | { |
74 | try { |
75 | r.release(); |
76 | } |
77 | catch (const Exception&) |
78 | { |
79 | DtorException::devHalt(); |
80 | } |
81 | } |
82 | |
83 | private: |
84 | RefCounted& r; |
85 | }; |
86 | |
87 | enum NoIncrement {REF_NO_INCR}; |
88 | |
89 | // controls reference counter of the object where points |
90 | template <typename T> |
91 | class RefPtr |
92 | { |
93 | public: |
94 | RefPtr() : ptr(NULL) |
95 | { } |
96 | |
97 | explicit RefPtr(T* p) : ptr(p) |
98 | { |
99 | if (ptr) |
100 | { |
101 | ptr->addRef(); |
102 | } |
103 | } |
104 | |
105 | // This special form of ctor is used to create refcounted ptr from interface, |
106 | // returned by a function (which increments counter on return) |
107 | RefPtr(NoIncrement x, T* p) : ptr(p) |
108 | { } |
109 | |
110 | RefPtr(const RefPtr& r) : ptr(r.ptr) |
111 | { |
112 | if (ptr) |
113 | { |
114 | ptr->addRef(); |
115 | } |
116 | } |
117 | |
118 | ~RefPtr() |
119 | { |
120 | if (ptr) |
121 | { |
122 | ptr->release(); |
123 | } |
124 | } |
125 | |
126 | T* assignRefNoIncr(T* p) |
127 | { |
128 | assign(NULL); |
129 | ptr = p; |
130 | return ptr; |
131 | } |
132 | |
133 | T* operator=(T* p) |
134 | { |
135 | return assign(p); |
136 | } |
137 | |
138 | T* operator=(const RefPtr& r) |
139 | { |
140 | return assign(r.ptr); |
141 | } |
142 | |
143 | operator T*() |
144 | { |
145 | return ptr; |
146 | } |
147 | |
148 | T* operator->() |
149 | { |
150 | return ptr; |
151 | } |
152 | |
153 | operator const T*() const |
154 | { |
155 | return ptr; |
156 | } |
157 | |
158 | const T* operator->() const |
159 | { |
160 | return ptr; |
161 | } |
162 | |
163 | /* NS: you cannot have operator bool here. It creates ambiguity with |
164 | operator T* with some of the compilers (at least VS2003) |
165 | |
166 | operator bool() const |
167 | { |
168 | return ptr ? true : false; |
169 | }*/ |
170 | |
171 | bool hasData() const |
172 | { |
173 | return ptr ? true : false; |
174 | } |
175 | |
176 | bool operator !() const |
177 | { |
178 | return !ptr; |
179 | } |
180 | |
181 | bool operator ==(const RefPtr& r) const |
182 | { |
183 | return ptr == r.ptr; |
184 | } |
185 | |
186 | bool operator !=(const RefPtr& r) const |
187 | { |
188 | return ptr != r.ptr; |
189 | } |
190 | |
191 | T* getPtr() |
192 | { |
193 | return ptr; |
194 | } |
195 | |
196 | private: |
197 | T* assign(T* const p) |
198 | { |
199 | if (ptr != p) |
200 | { |
201 | if (p) |
202 | { |
203 | p->addRef(); |
204 | } |
205 | if (ptr) |
206 | { |
207 | ptr->release(); |
208 | } |
209 | |
210 | ptr = p; |
211 | } |
212 | |
213 | return ptr; |
214 | } |
215 | |
216 | T* ptr; |
217 | }; |
218 | |
219 | template <typename T> |
220 | class AnyRef : public T, public RefCounted |
221 | { |
222 | public: |
223 | inline AnyRef() : T() {} |
224 | inline AnyRef(const T& v) : T(v) {} |
225 | inline explicit AnyRef(MemoryPool& p) : T(p) {} |
226 | inline AnyRef(MemoryPool& p, const T& v) : T(p, v) {} |
227 | }; |
228 | } // namespace |
229 | |
230 | #endif // COMMON_REF_COUNTED_H |
231 | |