blob: 6bbed7125d5e0b6311ff051aeb3c2029890196a1 [file] [log] [blame]
Alexandre Lisionddd731e2014-01-31 11:50:08 -05001// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2//
3// This file is part of GNU uCommon C++.
4//
5// GNU uCommon C++ is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published
7// by the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// GNU uCommon C++ is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * A common object base class with auto-pointer support.
20 * A common object class is used which may be referenced counted and
21 * associated with a smart auto-pointer class. A lot of the things
22 * found here were inspired by working with Objective-C. Many of the
23 * classes are designed to offer automatic heap management through
24 * smart pointers and temporary objects controlled through the scope of
25 * the stack frame of method calls.
26 * @file ucommon/object.h
27 */
28
29#ifndef _UCOMMON_OBJECT_H_
30#define _UCOMMON_OBJECT_H_
31
32#ifndef _UCOMMON_CPR_H_
33#include <ucommon/cpr.h>
34#endif
35
36#ifndef _UCOMMON_GENERICS_H_
37#include <ucommon/generics.h>
38#endif
39
40#ifndef _UCOMMON_PROTOCOLS_H_
41#include <ucommon/protocols.h>
42#endif
43
44#include <stdlib.h>
45
46NAMESPACE_UCOMMON
47
48/**
49 * A base class for reference counted objects. Reference counted objects
50 * keep track of how many objects refer to them and fall out of scope when
51 * they are no longer being referred to. This can be used to achieve
52 * automatic heap management when used in conjunction with smart pointers.
53 * @author David Sugar <dyfet@gnutelephony.org>
54 */
55class __EXPORT CountedObject : public ObjectProtocol
56{
57private:
58 volatile unsigned count;
59
60protected:
61 /**
62 * Construct a counted object, mark initially as unreferenced.
63 */
64 CountedObject();
65
66 /**
67 * Construct a copy of a counted object. Our instance is not a
68 * reference to the original object but a duplicate, so we do not
69 * retain the original and we do reset our count to mark as
70 * initially unreferenced.
71 */
72 CountedObject(const ObjectProtocol &ref);
73
74 /**
75 * Dealloc object no longer referenced. The dealloc routine would commonly
76 * be used for a self delete to return the object back to a heap when
77 * it is no longer referenced.
78 */
79 virtual void dealloc(void);
80
81 /**
82 * Force reset of count.
83 */
84 inline void reset(void)
85 {count = 0;}
86
87public:
88 /**
89 * Test if the object has copied references. This means that more than
90 * one object has a reference to our object.
91 * @return true if referenced by more than one object.
92 */
93 inline bool is_copied(void)
94 {return count > 1;};
95
96 /**
97 * Test if the object has been referenced (retained) by anyone yet.
98 * @return true if retained.
99 */
100 inline bool is_retained(void)
101 {return count > 0;};
102
103 /**
104 * Return the number of active references (retentions) to our object.
105 * @return number of references to our object.
106 */
107 inline unsigned copied(void)
108 {return count;};
109
110 /**
111 * Increase reference count when retained.
112 */
113 void retain(void);
114
115 /**
116 * Decrease reference count when released. If no longer retained, then
117 * the object is dealloc'd.
118 */
119 void release(void);
120};
121
122/**
123 * A general purpose smart pointer helper class. This is particularly
124 * useful in conjunction with reference counted objects which can be
125 * managed and automatically removed from the heap when they are no longer
126 * being referenced by a smart pointer. The smart pointer itself would
127 * normally be constructed and initialized as an auto variable in a method
128 * call, and will dereference the object when the pointer falls out of scope.
129 * This is actually a helper class for the typed pointer template.
130 * @author David Sugar <dyfet@gnutelephony.org>
131 */
132class __EXPORT auto_object
133{
134protected:
135 ObjectProtocol *object;
136
137 auto_object();
138
139public:
140 /**
141 * Construct an auto-pointer referencing an existing object.
142 * @param object we point to.
143 */
144 auto_object(ObjectProtocol *object);
145
146 /**
147 * Construct an auto-pointer as a copy of another pointer. The
148 * retention of the object being pointed to will be increased.
149 * @param pointer we are a copy of.
150 */
151 auto_object(const auto_object &pointer);
152
153 /**
154 * Delete auto pointer. When it falls out of scope, the retention
155 * of the object it references is reduced. If it falls to zero in
156 * a reference counted object, then the object is auto-deleted.
157 */
158 ~auto_object();
159
160 /**
161 * Manually release the pointer. This reduces the retention level
162 * of the object and resets the pointer to point to nobody.
163 */
164 void release(void);
165
166 /**
167 * Test if the pointer is not set.
168 * @return true if the pointer is not referencing anything.
169 */
170 bool operator!() const;
171
172 /**
173 * Test if the pointer is referencing an object.
174 * @return true if the pointer is currently referencing an object.
175 */
176 operator bool() const;
177
178 /**
179 * test if the object being referenced is the same as the object we specify.
180 * @param object we compare to.
181 * @return true if this is the object our pointer references.
182 */
183 bool operator==(ObjectProtocol *object) const;
184
185 /**
186 * test if the object being referenced is not the same as the object we specify.
187 * @param object we compare to.
188 * @return true if this is not the object our pointer references.
189 */
190 bool operator!=(ObjectProtocol *object) const;
191
192 /**
193 * Set our pointer to a specific object. If the pointer currently
194 * references another object, that object is released. The pointer
195 * references our new object and that new object is retained.
196 * @param object to assign to.
197 */
198 void operator=(ObjectProtocol *object);
199};
200
201/**
202 * A sparse array of managed objects. This might be used as a simple
203 * array class for reference counted objects. This class assumes that
204 * objects in the array exist when assigned, and that gaps in the array
205 * are positions that do not reference any object. Objects are automatically
206 * created (create on access/modify when an array position is referenced
207 * for the first time. This is an abstract class because it is a type
208 * factory for objects who's derived class form constructor is not known
209 * in advance and is a helper class for the sarray template.
210 * @author David Sugar <dyfet@gnutelephony.org>
211 */
212class __EXPORT SparseObjects
213{
214private:
215 ObjectProtocol **vector;
216 unsigned max;
217
218protected:
219 /**
220 * Object factory for creating members of the spare array when they
221 * are initially requested.
222 * @return new object.
223 */
224 virtual ObjectProtocol *create(void) = 0;
225
226 /**
227 * Purge the array by deleting all created objects.
228 */
229 void purge(void);
230
231 virtual ObjectProtocol *invalid(void) const;
232
233 /**
234 * Get (reference) an object at a specified offset in the array.
235 * @param offset in array.
236 * @return new or existing object.
237 */
238 ObjectProtocol *get(unsigned offset);
239
240 /**
241 * Create a sparse array of known size. No member objects are
242 * created until they are referenced.
243 * @param size of array.
244 */
245 SparseObjects(unsigned size);
246
247 /**
248 * Destroy sparse array and delete all generated objects.
249 */
250 virtual ~SparseObjects();
251
252public:
253 /**
254 * Get count of array elements.
255 * @return array elements.
256 */
257 unsigned count(void);
258};
259
260/**
261 * Generate a typed sparse managed object array. Members in the array
262 * are created when they are first referenced. The types for objects
263 * that are generated by sarray must have Object as a base class. Managed
264 * sparse arrays differ from standard arrays in that the member elements
265 * are not allocated from the heap when the array is created, but rather
266 * as they are needed.
267 * @author David Sugar <dyfet@gnutelephony.org>
268 */
269template <class T>
270class sarray : public SparseObjects
271{
272public:
273 /**
274 * Generate a sparse typed array of specified size.
275 * @param size of array to create.
276 */
277 inline sarray(unsigned size) : SparseObjects(size) {};
278
279 /**
280 * Get typed member of array. If the object does not exist, it is
281 * created.
282 * @param offset in array for object.
283 * @return pointer to typed object.
284 */
285 inline T *get(unsigned offset)
286 {return static_cast<T*>(SparseObjects::get(offset));}
287
288 /**
289 * Array operation to access member object. If the object does not
290 * exist, it is created.
291 * @param offset in array for object.
292 * @return pointer to typed object.
293 */
294 inline T& operator[](unsigned offset)
295 {return get(offset);};
296
297 inline const T* at(unsigned offset)
298 {return static_cast<const T&>(SparseObjects::get(offset));}
299
300private:
301 __LOCAL ObjectProtocol *create(void)
302 {return new T;};
303};
304
305/**
306 * Template for embedding a data structure into a reference counted object.
307 * This is a convenient means to create reference counted heap managed data
308 * structure. This template can be used for embedding data into other kinds
309 * of managed object classes in addition to reference counting. For example,
310 * it can be used to embed a data structure into a linked list, as shown in
311 * the linked_value template.
312 * @author David Sugar <dyfet@gnutelephony.org>
313 */
314template <typename T, class O = CountedObject>
315class object_value : public O
316{
317protected:
318 /**
319 * Assign our value from a typed data object. This is a helper method.
320 * @param object to assign our value from.
321 */
322 inline void set(const T& object)
323 {value = object;};
324
325public:
326 T value; /**< Embedded data value */
327
328 /**
329 * Construct composite value object.
330 */
331 inline object_value() : O() {};
332
333 /**
334 * Construct composite value object and assign from existing data value.
335 * @param existing typed value to assign.
336 */
337 inline object_value(T& existing) : O()
338 {value = existing;};
339
340 /**
341 * Pointer reference to embedded data value.
342 * @return embedded value.
343 */
344 inline T& operator*()
345 {return value;};
346
347 /**
348 * Assign embedded data value.
349 * @param data value to assign.
350 */
351 inline void operator=(const T& data)
352 {value = data;};
353
354 /**
355 * Retrieve data value by casting reference.
356 * @return embedded value.
357 */
358 inline operator T&()
359 {return value;};
360
361 inline T& operator()()
362 {return value;};
363
364 /**
365 * Set data value by expression reference.
366 * @param data value to assign.
367 */
368 inline void operator()(T& data)
369 {value = data;};
370};
371
372/**
373 * Typed smart pointer class. This is used to manage references to
374 * a specific typed object on the heap that is derived from the base Object
375 * class. This is most commonly used to manage references to reference
376 * counted heap objects so their heap usage can be auto-managed while there
377 * is active references to such objects. Pointers are usually created on
378 * the stack frame and used to reference an object during the life of a
379 * member function. They can be created in other objects that live on the
380 * heap and can be used to maintain active references so long as the object
381 * they are contained in remains in scope as well.
382 * @author David Sugar <dyfet@gnutelephony.org>
383 */
384template <class T, class P = auto_object>
385class object_pointer : public P
386{
387public:
388 /**
389 * Create a pointer with no reference.
390 */
391 inline object_pointer() : P() {};
392
393 /**
394 * Create a pointer with a reference to a heap object.
395 * @param object we are referencing.
396 */
397 inline object_pointer(T* object) : P(object) {};
398
399 /**
400 * Reference object we are pointing to through pointer indirection.
401 * @return pointer to object we are pointing to.
402 */
403 inline T* operator*() const
404 {return static_cast<T*>(P::object);};
405
406 /**
407 * Reference object we are pointing to through function reference.
408 * @return object we are pointing to.
409 */
410 inline T& operator()() const
411 {return *(static_cast<T*>(P::object));};
412
413 /**
414 * Reference member of object we are pointing to.
415 * @return reference to member of pointed object.
416 */
417 inline T* operator->() const
418 {return static_cast<T*>(P::object);};
419
420 /**
421 * Get pointer to object.
422 * @return pointer or NULL if we are not referencing an object.
423 */
424 inline T* get(void) const
425 {return static_cast<T*>(P::object);};
426
427 /**
428 * Iterate our pointer if we reference an array on the heap.
429 * @return next object in array.
430 */
431 inline T* operator++()
432 {P::operator++(); return get();};
433
434 /**
435 * Iterate our pointer if we reference an array on the heap.
436 * @return previous object in array.
437 */
438 inline void operator--()
439 {P::operator--(); return get();};
440
441 /**
442 * Perform assignment operator to existing object.
443 * @param typed object to assign.
444 */
445 inline void operator=(T *typed)
446 {P::operator=((ObjectProtocol *)typed);};
447
448 /**
449 * See if pointer is set.
450 */
451 inline operator bool()
452 {return P::object != NULL;};
453
454 /**
455 * See if pointer is not set.
456 */
457 inline bool operator!()
458 {return P::object == NULL;};
459};
460
461/**
462 * Convenience function to access object retention.
463 * @param object we are retaining.
464 */
465inline void retain(ObjectProtocol *object)
466 {object->retain();}
467
468/**
469 * Convenience function to access object release.
470 * @param object we are releasing.
471 */
472inline void release(ObjectProtocol *object)
473 {object->release();}
474
475/**
476 * Convenience function to access object copy.
477 * @param object we are copying.
478 */
479inline ObjectProtocol *copy(ObjectProtocol *object)
480 {return object->copy();}
481
482END_NAMESPACE
483
484#endif