blob: 207c7ebddd0afa880f47e7c62856baee1b93709d [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 * Basic array and reusable object factory heap support.
20 * This offers ucommon support for vector arrays, and for forming
21 * reusable object pools. Reusable object pools can be tied to local
22 * heaps and offer a means to create type factories that do not require
23 * global locking through malloc.
24 * @file ucommon/vector.h
25 */
26
27#ifndef _UCOMMON_VECTOR_H_
28#define _UCOMMON_VECTOR_H_
29
30#ifndef _UCOMMON_THREAD_H_
31#include <ucommon/thread.h>
32#endif
33
34typedef unsigned short vectorsize_t;
35
36NAMESPACE_UCOMMON
37
38/**
39 * An array of reusable objects. This class is used to support the
40 * array_use template. A pool of objects are created which can be
41 * allocated as needed. Deallocated objects are returned to the pool
42 * so they can be reallocated later. This is a private fixed size heap.
43 * @author David Sugar <dyfet@gnutelephony.org>
44 */
45class __EXPORT ArrayReuse : public ReusableAllocator
46{
47private:
48 size_t objsize;
49 unsigned count, limit, used;
50 caddr_t mem;
51
52protected:
53 ArrayReuse(size_t objsize, unsigned c);
54 ArrayReuse(size_t objsize, unsigned c, void *memory);
55
56public:
57 /**
58 * Destroy reusable private heap array.
59 */
60 ~ArrayReuse();
61
62protected:
63 bool avail(void);
64
65 ReusableObject *get(timeout_t timeout);
66 ReusableObject *get(void);
67 ReusableObject *request(void);
68};
69
70/**
71 * A mempager source of reusable objects. This is used by the reuse_pager
72 * template to allocate new objects either from a memory pager used as
73 * a private heap, or from previously allocated objects that have been
74 * returned for reuse.
75 * @author David Sugar <dyfet@gnutelephony.org>
76 */
77class __EXPORT PagerReuse : protected MemoryRedirect, protected ReusableAllocator
78{
79private:
80 unsigned limit, count;
81 size_t osize;
82
83protected:
84 PagerReuse(mempager *pager, size_t objsize, unsigned count);
85 ~PagerReuse();
86
87 bool avail(void);
88 ReusableObject *get(void);
89 ReusableObject *get(timeout_t timeout);
90 ReusableObject *request(void);
91};
92
93/**
94 * A managed vector for generic object pointers. This vector is memory
95 * managed at runtime by basic cow (copy-on-write) operations of a reference
96 * counted object list. This allows the size of the vector to be changed
97 * at runtime and for the vector to be copied by managing reference counted
98 * copies of the list of objects as needed.
99 *
100 * This class is somewhat analogous to the string class, but rather than
101 * holding a string "array of chars" that may be re-sized and reallocated,
102 * the Vector holds an array of Object pointers. Since the object pointers
103 * we store in the vector are objects inherited from Object, a vector can
104 * itself act as a vector of smart pointers to reference counted objects
105 * (derived from CountedObject).
106 * @author David Sugar <dyfet@gnutelephony.org>.
107 */
108class __EXPORT Vector
109{
110public:
111 class __EXPORT array : public CountedObject
112 {
113 public:
114#pragma pack(1)
115 vectorsize_t max, len;
116 ObjectProtocol *list[1];
117#pragma pack()
118
119 array(vectorsize_t size);
120 void dealloc(void);
121 void set(ObjectProtocol **items);
122 void add(ObjectProtocol **list);
123 void add(ObjectProtocol *obj);
124 void purge(void);
125 void inc(vectorsize_t adj);
126 void dec(vectorsize_t adj);
127 };
128
129protected:
130 array *data;
131
132 array *create(vectorsize_t size) const;
133
134 virtual void release(void);
135 virtual void cow(vectorsize_t adj = 0);
136 ObjectProtocol **list(void) const;
137
138 friend class Vector::array;
139
140protected:
141 /**
142 * Object handler for index outside vector range.
143 * @return default object, often NULL.
144 */
145 virtual ObjectProtocol *invalid(void) const;
146
147public:
148 /**
149 * npos is a constant for an "invalid" position value.
150 */
151 static const vectorsize_t npos;
152
153 /**
154 * Create an initially empty vector.
155 */
156 Vector();
157
158 /**
159 * Create a vector of size object pointers.
160 * @param size of vector to create.
161 */
162 Vector(vectorsize_t size);
163
164 /**
165 * Create a vector of size objects from existing object pointers.
166 * This allocates the vector and initializes the object pointers from
167 * an existing array of object pointers. Either a specific vector
168 * size may be used, or the end of the vector will be found by a NULL
169 * object pointer.
170 * @param items to place into the vector.
171 * @param size of the vector to create, or use NULL item for end.
172 */
173 Vector(ObjectProtocol **items, vectorsize_t size = 0);
174
175 /**
176 * Destroy the current reference counted vector of object pointers.
177 */
178 virtual ~Vector();
179
180 /**
181 * Get the size of the vector (number of active members).
182 * @return number of active pointers in vector.
183 */
184 vectorsize_t len(void) const;
185
186 /**
187 * Get the effective allocation space used by the vector. This is the
188 * number of pointers it can hold before it needs to be resized.
189 * @return storage size of vector.
190 */
191 vectorsize_t size(void) const;
192
193 /**
194 * Get an object pointer from a specified member of the vector.
195 * @param index of member pointer to return. Negative values from end.
196 * @return object pointer of member.
197 */
198 ObjectProtocol *get(int index) const;
199
200 /**
201 * Copy the vector to an external pointer array.
202 * @param mem array of external pointers to hold vector.
203 * @param max size of the external array.
204 * @return number of elements copied into external array.
205 */
206 vectorsize_t get(void **mem, vectorsize_t max) const;
207
208 /**
209 * Get the first object pointer contained in the vector. Typically used
210 * in iterations.
211 * @return first object pointer.
212 */
213 ObjectProtocol *begin(void) const;
214
215 /**
216 * Get the last object pointer contained in the vector. Typically used
217 * in iterations.
218 * @return last object pointer.
219 */
220 ObjectProtocol *end(void) const;
221
222 /**
223 * Find the first instance of a specific pointer in the vector.
224 * @param pointer to locate in the vector.
225 * @param offset to start searching in vector.
226 * @return position of pointer in vector or npos if not found.
227 */
228 vectorsize_t find(ObjectProtocol *pointer, vectorsize_t offset = 0) const;
229
230 /**
231 * Split the vector at a specified offset. All members after the split
232 * are de-referenced and dropped from the vector.
233 * @param position to split vector at.
234 */
235 void split(vectorsize_t position);
236
237 /**
238 * Split the vector after a specified offset. All members before the split
239 * are de-referenced and dropped. The member starting at the split point
240 * becomes the first member of the vector.
241 * @param position to split vector at.
242 */
243 void rsplit(vectorsize_t position);
244
245 /**
246 * Set a member of the vector to an object. If an existing member was
247 * present and is being replaced, it is de-referenced.
248 * @param position in vector to place object pointer.
249 * @param pointer to place in vector.
250 */
251 void set(vectorsize_t position, ObjectProtocol *pointer);
252
253 /**
254 * Set the vector to a list of objects terminated by a NULL pointer.
255 * @param list of object pointers.
256 */
257 void set(ObjectProtocol **list);
258
259 /**
260 * Add (append) a NULL terminated list of objects to the vector.
261 * @param list of object pointers to add.
262 */
263 void add(ObjectProtocol **list);
264
265 /**
266 * Add (append) a single object pointer to the vector.
267 * @param pointer to add to vector.
268 */
269 void add(ObjectProtocol *pointer);
270
271 /**
272 * De-reference and remove all pointers from the vector.
273 */
274 void clear(void);
275
276 /**
277 * Re-size & re-allocate the total (allocated) size of the vector.
278 * @param size to allocate for vector.
279 */
280 virtual bool resize(vectorsize_t size);
281
282 /**
283 * Set (duplicate) an existing vector into our vector.
284 * @param vector to duplicate.
285 */
286 inline void set(Vector &vector)
287 {set(vector.list());};
288
289 /**
290 * Add (append) an existing vector to our vector.
291 * @param vector to append.
292 */
293 inline void add(Vector &vector)
294 {add(vector.list());};
295
296 /**
297 * Return a pointer from the vector by array reference.
298 * @param index of vector member pointer to return.
299 */
300 inline ObjectProtocol *operator[](int index)
301 {return get(index);};
302
303 /**
304 * Assign a member of the vector directly.
305 * @param position to assign.
306 * @param pointer to object to assign to vector.
307 */
308 inline void operator()(vectorsize_t position, ObjectProtocol *pointer)
309 {set(position, pointer);};
310
311 /**
312 * Retrieve a member of the vector directly.
313 * @param position to retrieve object from.
314 * @return object pointer retrieved from vector.
315 */
316 inline ObjectProtocol *operator()(vectorsize_t position)
317 {return get(position);};
318
319 /**
320 * Append a member to the vector directly.
321 * @param pointer to object to add to vector.
322 */
323 inline void operator()(ObjectProtocol *pointer)
324 {add(pointer);};
325
326 /**
327 * Assign (copy) into our existing vector from another vector.
328 * @param vector to assign from.
329 */
330 inline void operator=(Vector &vector)
331 {set(vector.list());};
332
333 /**
334 * Append into our existing vector from another vector.
335 * @param vector to append from.
336 */
337 inline void operator+=(Vector &vector)
338 {add(vector.list());};
339
340 /**
341 * Concatenate into our existing vector from assignment list.
342 * @param vector to append from.
343 */
344 inline Vector& operator+(Vector &vector)
345 {add(vector.list()); return *this;};
346
347 /**
348 * Release vector and concat vector from another vector.
349 * @param vector to assign from.
350 */
351 Vector &operator^(Vector &vector);
352
353 /**
354 * Release our existing vector and duplicate from another vector. This
355 * differs from assign in that the allocated size of the vector is reset
356 * to the new list.
357 * @param vector to assign from.
358 */
359 void operator^=(Vector &vector);
360
361 /**
362 * Drop first member of vector.
363 */
364 void operator++();
365
366 /**
367 * Drop last member of the vector.
368 */
369 void operator--();
370
371 /**
372 * Drop first specified members from the vector.
373 * @param count of members to drop.
374 */
375 void operator+=(vectorsize_t count);
376
377 /**
378 * Drop last specified members from the vector.
379 * @param count of members to drop.
380 */
381 void operator-=(vectorsize_t count);
382
383 /**
384 * Compute the effective vector size of a list of object pointers.
385 * The size is found as the NULL pointer in the list.
386 * @return size of list.
387 */
388 static vectorsize_t size(void **list);
389};
390
391/**
392 * Vector with fixed size member list. This is analogous to the memstring
393 * class and is used to tie a vector to a fixed list in memory.
394 * @author David Sugar <dyfet@gnutelephony.org>
395 */
396class __EXPORT MemVector : public Vector
397{
398private:
399 bool resize(vectorsize_t size);
400 void cow(vectorsize_t adj = 0);
401 void release(void);
402
403 friend class Vector::array;
404
405public:
406 /**
407 * Create and manage a vector stored in fixed memory.
408 * @param pointer to where our vector list lives.
409 * @param size of vector list in memory.
410 */
411 MemVector(void *pointer, vectorsize_t size);
412
413 /**
414 * Destroy the vector.
415 */
416 ~MemVector();
417
418 /**
419 * Assign an existing vector into our fixed vector list.
420 * @param vector to copy from.
421 */
422 inline void operator=(Vector &vector)
423 {set(vector);};
424
425};
426
427/**
428 * A templated vector for a list of a specific Object subtype. The
429 * templated type must be derived from Object.
430 * @author David Sugar <dyfet@gnutelephony.org>
431 */
432template<class T>
433class vectorof : public Vector
434{
435public:
436 /**
437 * Create an empty vector for specified type.
438 */
439 inline vectorof() : Vector() {};
440
441 /**
442 * Create an empty vector of allocated size for specified type.
443 * @param size of vector to allocate.
444 */
445 inline vectorof(vectorsize_t size) : Vector(size) {};
446
447 inline T& operator[](int index)
448 {return static_cast<T&>(Vector::get(index));};
449
450 inline const T& at(int index)
451 {return static_cast<const T&>(Vector::get(index));};
452
453 /**
454 * Retrieve a typed member of the vector directly.
455 * @param position to retrieve object from.
456 * @return typed object pointer retrieved from vector.
457 */
458 inline T *operator()(vectorsize_t position)
459 {return static_cast<T *>(Vector::get(position));};
460
461 /**
462 * Get the first typed object pointer contained in the vector.
463 * @return first typed object pointer.
464 */
465 inline T *begin(void)
466 {return static_cast<T *>(Vector::begin());};
467
468 /**
469 * Get the last typed object pointer contained in the vector.
470 * @return last typed object pointer.
471 */
472 inline T *end(void)
473 {return static_cast<T *>(Vector::end());};
474
475 /**
476 * Concatenate typed vector in an expression.
477 * @param vector to concatenate.
478 * @return effective object to continue in expression.
479 */
480 inline Vector &operator+(Vector &vector)
481 {Vector::add(vector); return static_cast<Vector &>(*this);};
482};
483
484/**
485 * An array of reusable types. A pool of typed objects is created which can
486 * be allocated as needed. Deallocated typed objects are returned to the pool
487 * so they can be reallocated later. This is a private fixed size heap.
488 * @author David Sugar <dyfet@gnutelephony.org>
489 */
490template<class T>
491class array_reuse : protected ArrayReuse
492{
493public:
494 /**
495 * Create private heap of reusable objects of specified type.
496 * @param count of objects of specified type to allocate.
497 */
498 inline array_reuse(unsigned count) :
499 ArrayReuse(sizeof(T), count) {};
500
501 /**
502 * Create reusable objects of specific type in preallocated memory.
503 * @param count of objects of specified type in memory.
504 * @param memory to use.
505 */
506 inline array_reuse(unsigned count, void *memory) :
507 ArrayReuse(sizeof(T), count, memory) {};
508
509 /**
510 * Test if typed objects available in heap or re-use list.
511 * @return true if objects still are available.
512 */
513 inline operator bool() const
514 {return avail();};
515
516 /**
517 * Test if the entire heap has been allocated.
518 * @return true if no objects are available.
519 */
520 inline bool operator!() const
521 {return !avail();};
522
523 /**
524 * Request immediately next available typed object from the heap.
525 * @return typed object pointer or NULL if heap is empty.
526 */
527 inline T* request(void)
528 {return static_cast<T*>(ArrayReuse::request());};
529
530 /**
531 * Get a typed object from the heap. This function blocks when the
532 * heap is empty until an object is returned to the heap.
533 * @return typed object pointer from heap.
534 */
535 inline T* get(void)
536 {return static_cast<T*>(ArrayReuse::get());};
537
538 /**
539 * Create a typed object from the heap. This function blocks when the
540 * heap is empty until an object is returned to the heap.
541 * @return typed object pointer from heap.
542 */
543 inline T* create(void)
544 {return init<T>(static_cast<T*>(ArrayReuse::get()));};
545
546 /**
547 * Get a typed object from the heap. This function blocks until the
548 * the heap has an object to return or the timer has expired.
549 * @param timeout to wait for heap in milliseconds.
550 * @return typed object pointer from heap or NULL if timeout.
551 */
552 inline T* get(timeout_t timeout)
553 {return static_cast<T*>(ArrayReuse::get(timeout));};
554
555 /**
556 * Create a typed object from the heap. This function blocks until the
557 * the heap has an object to return or the timer has expired.
558 * @param timeout to wait for heap in milliseconds.
559 * @return typed object pointer from heap or NULL if timeout.
560 */
561 inline T* create(timeout_t timeout)
562 {return init<T>(static_cast<T*>(ArrayReuse::get(timeout)));};
563
564 /**
565 * Release (return) a typed object back to the heap for re-use.
566 * @param object to return.
567 */
568 inline void release(T *object)
569 {ArrayReuse::release(object);};
570
571 /**
572 * Get a typed object from the heap by type casting reference. This
573 * function blocks while the heap is empty.
574 * @return typed object pointer from heap.
575 */
576 inline operator T*()
577 {return array_reuse::get();};
578
579 /**
580 * Get a typed object from the heap by pointer reference. This
581 * function blocks while the heap is empty.
582 * @return typed object pointer from heap.
583 */
584 inline T *operator*()
585 {return array_reuse::get();};
586};
587
588/**
589 * A reusable private pool of reusable types. A pool of typed objects is
590 * created which can be allocated from a memory pager. Deallocated typed
591 * objects are also returned to this pool so they can be reallocated later.
592 * @author David Sugar <dyfet@gnutelephony.org>
593 */
594template <class T>
595class paged_reuse : protected PagerReuse
596{
597public:
598 /**
599 * Create a managed reusable typed object pool. This manages a heap of
600 * typed objects that can either be reused from released objects or
601 * allocate from an existing memory pager pool.
602 * @param pager pool to allocate from.
603 * @param count of objects of specified type to allocate.
604 */
605 inline paged_reuse(mempager *pager, unsigned count) :
606 PagerReuse(pager, sizeof(T), count) {};
607
608 /**
609 * Test if typed objects available from the pager or re-use list.
610 * @return true if objects still are available.
611 */
612 inline operator bool() const
613 {return PagerReuse::avail();};
614
615 /**
616 * Test if no objects are available for reuse or the pager.
617 * @return true if no objects are available.
618 */
619 inline bool operator!() const
620 {return !PagerReuse::avail();};
621
622 /**
623 * Get a typed object from the pager heap. This function blocks when the
624 * heap is empty until an object is returned to the heap.
625 * @return typed object pointer from heap.
626 */
627 inline T *get(void)
628 {return static_cast<T*>(PagerReuse::get());};
629
630 /**
631 * Get a typed object from the pager heap. This function blocks when the
632 * heap is empty until an object is returned to the heap. The objects
633 * default constructor is used.
634 * @return typed object pointer from heap.
635 */
636 inline T *create(void)
637 {return init<T>(static_cast<T*>(PagerReuse::get()));};
638
639 /**
640 * Get a typed object from the heap. This function blocks until the
641 * the heap has an object to return or the timer has expired.
642 * @param timeout to wait for heap in milliseconds.
643 * @return typed object pointer from heap or NULL if timeout.
644 */
645 inline T *get(timeout_t timeout)
646 {return static_cast<T*>(PagerReuse::get(timeout));};
647
648 /**
649 * Create a typed object from the heap. This function blocks until the
650 * the heap has an object to return or the timer has expired. The
651 * objects default constructor is used.
652 * @param timeout to wait for heap in milliseconds.
653 * @return typed object pointer from heap or NULL if timeout.
654 */
655 inline T *create(timeout_t timeout)
656 {return init<T>(static_cast<T*>(PagerReuse::get(timeout)));};
657
658 /**
659 * Request immediately next available typed object from the pager heap.
660 * @return typed object pointer or NULL if heap is empty.
661 */
662 inline T *request(void)
663 {return static_cast<T*>(PagerReuse::request());};
664
665 /**
666 * Release (return) a typed object back to the pager heap for re-use.
667 * @param object to return.
668 */
669 inline void release(T *object)
670 {PagerReuse::release(object);};
671
672 /**
673 * Get a typed object from the pager heap by type casting reference. This
674 * function blocks while the heap is empty.
675 * @return typed object pointer from heap.
676 */
677 inline T *operator*()
678 {return paged_reuse::get();};
679
680 /**
681 * Get a typed object from the pager heap by pointer reference. This
682 * function blocks while the heap is empty.
683 * @return typed object pointer from heap.
684 */
685 inline operator T*()
686 {return paged_reuse::get();};
687};
688
689/**
690 * Allocated vector list of a specified type. This analogous to the stringbuf
691 * class and allows one to create a vector with it's member list as a single
692 * object that can live in the heap or that can be created at once and used as
693 * a auto variable.
694 * @author David Sugar <dyfet@gnutelephony.org>
695 */
696template<typename T, vectorsize_t S>
697class vectorbuf : public MemVector
698{
699private:
700 char buffer[sizeof(array) + (S * sizeof(void *))];
701
702public:
703 /**
704 * Construct fixed sized vector object in heap or stack.
705 */
706 inline vectorbuf() : MemVector(buffer, S) {};
707
708 /**
709 * Get object pointer of specified type from fixed vector.
710 * @param index of typed member to return, < 0 to use from end of list.
711 * @return typed object pointer of member.
712 */
713 inline const T& at(int index)
714 {return static_cast<const T&>(Vector::get(index));};
715
716 inline T& operator[](int index)
717 {return static_cast<T&>(Vector::get(index));};
718
719 /**
720 * Retrieve a typed member of the fixed vector directly.
721 * @param position to retrieve object from.
722 * @return typed object pointer retrieved from vector.
723 */
724 inline T *operator()(vectorsize_t position)
725 {return static_cast<T *>(Vector::get(position));};
726
727 /**
728 * Get the first typed object pointer contained in the fixed vector.
729 * @return first typed object pointer.
730 */
731 inline T *begin(void)
732 {return static_cast<T *>(Vector::begin());};
733
734 /**
735 * Get the last typed object pointer contained in the fixed vector.
736 * @return last typed object pointer.
737 */
738 inline T *end(void)
739 {return static_cast<T *>(Vector::end());};
740
741 /**
742 * Concatenate fixed typed vector in an expression.
743 * @param vector to concatenate.
744 * @return effective object to continue in expression.
745 */
746 inline Vector &operator+(Vector &vector)
747 {Vector::add(vector); return static_cast<Vector &>(*this);};
748};
749
750END_NAMESPACE
751
752#endif