1 /*
2 * Copyright 2006-2008 The FLWOR Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #pragma once
17 #ifndef ZORBA_RCHANDLE_H
18 #define ZORBA_RCHANDLE_H
19
20 #include <sstream>
21 #include <errno.h>
22
23 #include <zorba/config.h>
24
25 #include "common/common.h"
26
27 #include "zorbautils/fatal.h"
28
29 #include "zorbatypes/rclock.h"
30
31 #include "zorbaserialization/class_serializer.h"
32
33
34 namespace zorba
35 {
36
37 namespace serialization
38 {
39 class archiver;
40 }
41
42
43 /*******************************************************************************
44
45 Base class for reference counted objects
46
47 Any class wishing to take advantage of automatic reference counting
48 must inherit from this class.
49
50 rcobject encapsulates the reference count, as well as functions
51 for incrementing and decrementing the count. It also contains code
52 for destroying a value when it is no longer in use, i.e., when its
53 reference count becomes 0.
54
55 ********************************************************************************/
56 class ZORBA_DLL_PUBLIC RCObject : public serialization::SerializeBaseClass
57 {
58 protected:
59 mutable long theRefCount;
60
61 public:
62 SERIALIZABLE_CLASS(RCObject);
63
RCObject(::zorba::serialization::Archiver & ar)64 RCObject(::zorba::serialization::Archiver& ar)
65 :
66 ::zorba::serialization::SerializeBaseClass(),
67 theRefCount(0)
68 {
69 }
70
71 void serialize(::zorba::serialization::Archiver& ar);
72
73 public:
RCObject()74 RCObject()
75 :
76 ::zorba::serialization::SerializeBaseClass(),
77 theRefCount(0)
78 {
79 }
80
RCObject(const RCObject &)81 RCObject(const RCObject&)
82 :
83 ::zorba::serialization::SerializeBaseClass(),
84 theRefCount(0)
85 {
86 }
87
~RCObject()88 virtual ~RCObject() { }
89
90 RCObject& operator=(const RCObject&) { return *this; }
91
free()92 virtual void free() { delete this; }
93
getRefCount()94 long getRefCount() const { return theRefCount; }
95
96 void addReference(SYNC_CODE(RCLock* lock)) const;
97
98 void removeReference(SYNC_CODE(RCLock* lock));
99 };
100
101
102 /*******************************************************************************
103
104 ********************************************************************************/
105 class ZORBA_DLL_PUBLIC SimpleRCObject : public serialization::SerializeBaseClass
106 {
107 protected:
108 mutable long theRefCount;
109
110 public:
111 SERIALIZABLE_CLASS(SimpleRCObject);
112
SimpleRCObject(serialization::Archiver & ar)113 SimpleRCObject(serialization::Archiver& ar)
114 :
115 serialization::SerializeBaseClass(),
116 theRefCount(0)
117 {
118 }
119
120 void serialize(serialization::Archiver& ar);
121
122 public:
SimpleRCObject()123 SimpleRCObject()
124 :
125 serialization::SerializeBaseClass(),
126 theRefCount(0)
127 {
128 }
129
SimpleRCObject(const SimpleRCObject &)130 SimpleRCObject(const SimpleRCObject&)
131 :
132 serialization::SerializeBaseClass(),
133 theRefCount(0)
134 {
135 }
136
~SimpleRCObject()137 virtual ~SimpleRCObject() { }
138
139 SimpleRCObject& operator=(const SimpleRCObject&) { return *this; }
140
free()141 virtual void free() { delete this; }
142
getRefCount()143 long getRefCount() const { return theRefCount; }
144
addReference(SYNC_CODE (RCLock * lock))145 void addReference(SYNC_CODE(RCLock* lock)) const { ++theRefCount; }
146
removeReference(SYNC_CODE (RCLock * lock))147 void removeReference(SYNC_CODE(RCLock* lock))
148 {
149 if (--theRefCount == 0)
150 {
151 free();
152 return;
153 }
154 }
155
156 SYNC_CODE(RCLock* getRCLock() const { return NULL; })
157 };
158
159
160 /*******************************************************************************
161
162 rchandle = r(ef)c(ount)handle
163
164 Template class for smart pointers-to-T objects. T must support the RCObject
165 interface, typically by inheriting from RCObject
166
167 ********************************************************************************/
168 template<class T> class rchandle
169 {
170 public:
171 typedef T value_type;
172 typedef value_type* pointer;
173 typedef value_type const* const_pointer;
174 typedef value_type& reference;
175 typedef value_type const& const_reference;
176
177 protected:
178 T * p;
179
180 public:
181 union union_T
182 {
183 T** t;
184 void** v;
185 };
186
187 public:
p(ptr)188 rchandle(T* ptr = 0) : p(ptr)
189 {
190 init();
191 }
192
rchandle(rchandle const & rhs)193 rchandle(rchandle const& rhs) : p(rhs.getp())
194 {
195 init();
196 }
197
~rchandle()198 ~rchandle()
199 {
200 if (p)
201 p->removeReference(SYNC_CODE(p->getRCLock()));
202 p = 0;
203 }
204
isNull()205 bool isNull () const { return p == NULL; }
206
setNull()207 void setNull() { p = NULL;}
208
getp()209 T* getp() const { return p; }
210
getp_ref()211 union_T getp_ref() { union_T u_t; u_t.t = &p; return u_t;}
212
213 // rchandle const-ness is unclear. The implicit operators are more
214 // restrictive than the explicit cast() and getp() methods.
215 operator T* () { return getp(); }
216
217 operator const T * () const { return getp(); }
218
219 T* operator->() const { return p; }
220
221 T& operator*() const { return *p; }
222
223 bool operator!() const { return !p; }
224
225 bool operator==(rchandle const& h) const { return p == h.p; }
226 bool operator!=(rchandle const& h) const { return p != h.p; }
227 bool operator==(T const* pp) const { return p == pp; }
228 bool operator!=(T const* pp) const { return p != pp; }
229 bool operator<(const rchandle& h) const { return p < h.p; }
230
231
cast()232 template <class otherT> rchandle<otherT> cast() const
233 {
234 return rchandle<otherT> (static_cast<otherT *> (p));
235 }
236
dyn_cast()237 template <class otherT> rchandle<otherT> dyn_cast() const
238 {
239 return rchandle<otherT> (dynamic_cast<otherT *> (p));
240 }
241
242 template <class otherT> operator rchandle<otherT> ()
243 {
244 return cast<otherT> ();
245 }
246
247 template <class otherT> operator const rchandle<otherT> () const
248 {
249 return cast<otherT> ();
250 }
251
252 rchandle& operator=(const T* rhs)
253 {
254 if (p != rhs)
255 {
256 if (p) p->removeReference(SYNC_CODE(p->getRCLock()));
257 p = const_cast<T*>(rhs);
258 init();
259 }
260 return *this;
261 }
262
263 template <class otherT> rchandle& operator=(const otherT* rhs)
264 {
265 if (p != rhs)
266 {
267 if (p) p->removeReference(SYNC_CODE(p->getRCLock()));
268 p = static_cast<T*>(const_cast<otherT*>(rhs));
269 init();
270 }
271 return *this;
272 }
273
274 rchandle& operator=(rchandle const& rhs)
275 {
276 return assign (rhs);
277 }
278
279 template <class otherT> rchandle& operator=(rchandle<otherT> const& rhs)
280 {
281 return assign (rhs);
282 }
283
transfer(rchandle<otherT> & rhs)284 template <class otherT> rchandle& transfer(rchandle<otherT>& rhs)
285 {
286 if (p != rhs.getp())
287 {
288 if (p) p->removeReference(SYNC_CODE(p->getRCLock()));
289 p = static_cast<T*>(rhs.getp());
290 rhs.setNull();
291 }
292 return *this;
293 }
294
transfer(rchandle & rhs)295 rchandle& transfer(rchandle& rhs)
296 {
297 if (p != rhs.p)
298 {
299 if (p) p->removeReference(SYNC_CODE(p->getRCLock()));
300 p = rhs.p;
301 rhs.p = NULL;
302 }
303 return *this;
304 }
305
release()306 T* release()
307 {
308 T* tmp = p;
309 p = NULL;
310 return tmp;
311 }
312
313 public:
debug()314 std::string debug() const
315 {
316 std::ostringstream oss;
317 oss << "rchandle[refcount=" << p->getRefCount() << ']';
318 return oss.str();
319 }
320
321 protected:
init()322 void init()
323 {
324 if (p == 0) return;
325 p->addReference(SYNC_CODE(p->getRCLock()));
326 }
327
328
assign(const rchandle<otherT> & rhs)329 template <class otherT> rchandle& assign(const rchandle<otherT>& rhs)
330 {
331 if (p != rhs.getp())
332 {
333 if (p) p->removeReference(SYNC_CODE(p->getRCLock()));
334 p = static_cast<T*>(rhs.getp());
335 init();
336 }
337 return *this;
338 }
339
340 };
341
342
343 namespace ztd
344 {
345
346 template<typename T> inline
to_string(const rchandle<T> & r)347 std::string to_string(const rchandle<T>& r)
348 {
349 return !r ? "<null>" : to_string( *r );
350 }
351
352
353 template<typename T,class OutputStringType> inline
to_string(const rchandle<T> & r,OutputStringType * out)354 void to_string(const rchandle<T>& r, OutputStringType* out )
355 {
356 if ( !r )
357 *out = "<null>";
358 else
359 to_string( *r, out );
360 }
361
362 } // namespace ztd
363
364 /*******************************************************************************
365
366 ********************************************************************************/
367 template<class T> class const_rchandle : protected rchandle<T>
368 {
369 public:
370 const_rchandle (const T *_p = 0) : rchandle<T> (const_cast<T *> (_p)) {}
371
const_rchandle(const const_rchandle & rhs)372 const_rchandle (const const_rchandle &rhs) : rchandle<T> (rhs) {}
373
const_rchandle(rchandle<T> & rhs)374 const_rchandle (rchandle<T> &rhs) : rchandle<T> (rhs) {}
375
const_rchandle(::zorba::serialization::Archiver & ar)376 const_rchandle(::zorba::serialization::Archiver &ar) {}
377
378 const_rchandle& operator= (const const_rchandle &rhs) {
379 this->assign (rhs);
380 return *this;
381 }
382
383 public:
isNull()384 bool isNull () const { return rchandle<T>::isNull(); }
385
setNull()386 void setNull() { rchandle<T>::setNull();}
387
getp()388 const T* getp () const { return rchandle<T>::getp (); }
389
getp_ref()390 typename rchandle<T>::union_T getp_ref() { return rchandle<T>::getp_ref(); }
391
392 operator const T * () const { return rchandle<T>::getp (); }
393
394 const T* operator->() const { return getp(); }
395 const T& operator*() const { return *getp(); }
396
397 bool operator== (const_rchandle h) const { return rchandle<T>::operator== (h); }
398 bool operator!= (const_rchandle h) const { return rchandle<T>::operator!= (h); }
399 bool operator== (const T * pp) const { return rchandle<T>::operator== (pp); }
400 bool operator!= (const T * pp) const { return rchandle<T>::operator!= (pp); }
401 bool operator< (const_rchandle h) const { return rchandle<T>::operator< (h); }
402 };
403
404
405
406 /*******************************************************************************
407
408 ********************************************************************************/
409 namespace RCHelper
410 {
411 template<class T>
addReference(T * t)412 static void addReference(T *t)
413 {
414 t->addReference(SYNC_CODE(t->getRCLock()));
415 }
416
417 template<class T>
removeReference(T * t)418 static void removeReference(T *t)
419 {
420 t->removeReference(SYNC_CODE(t->getRCLock()));
421 }
422
423 template<class T>
addReference(rchandle<T> & t)424 static void addReference(rchandle<T> &t)
425 {
426 addReference(t.getp());
427 }
428
429 template<class T>
removeReference(rchandle<T> & t)430 static void removeReference(rchandle<T> &t)
431 {
432 removeReference(t.getp());
433 }
434 };
435
436 } // namespace zorba
437
438 #endif
439 /*
440 * Local variables:
441 * mode: c++
442 * End:
443 */
444 /* vim:set et sw=2 ts=2: */
445