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
31namespace 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