5 * A pvector is a dynamic pointer array implemented as an access tree
6 * of index pages of 256 pointers.
14 * A pvector_page is an array of 256 void* items.
16 typedef void* pvector_page[256];
21 * A pvector index is ether viewed in whole as an unsigned 64-bit
22 * integer, or in levels as 8 unsigned char level indexes. This
23 * implementation assumes LE integer layout.
26 unsigned long whole; // 64-bit unsigned integer
27 unsigned char level[8];
33 * A pvector is a compound of a size and a pvector_page pointer, which
34 * when non-null points out the top-most page of the pvector. The
35 * number of levels is derived from its size with level 0 being the
36 * leaf level of actual content. E.g., a pvector larger than 256
37 * items, has at least two levels, and generally N levels may span up
38 * to 256^N content entries.
40 typedef struct _pvector {
41 unsigned long size; //!< Limit for the logical entries[]
42 pvector_page *entries; //!< Pointer to entries indexing
45 // Number of slots for page S
46 #define PV_LEVEL_SIZE(S) ((int)(exp( 256, (S) )))
48 // The indexing part for level part p in index i
49 #define PV_PART(p,i) (((unsigned char*)&i)[p])
52 * Find the next used slot at given index or later. With a reclaim
53 * function, it will be invoked for verifying that the item is
54 * actually in use, in which case it returns 1. Otherwise it should
55 * reclaim any memory for the item and return 0;
57 void **pvector_next_used(
58 pvector *pv,unsigned long *index,
59 int (*reclaim)(pvector *pv,unsigned long index,void *item,void *data),
63 * Function: int pvector_resize(
64 * pvector *pv,unsigned long new_size,
65 * int (*reclaim)(pvector *,unsigned long,void *item,void *data),
72 * Tries to resize the given pvector to a new size. This may result in
73 * the introduction or removal of indexing pages, so that the leveling
74 * is consistent with the pvector size. Thus, if it grows into a new
75 * 256^N level, then one or more new upper level pages are inserted as
76 * needed. If it shrinks below the current level, then top-level pages
79 * Also, if the new size is smaller than currently, then the now
80 * excess tail of entries is scanned for any used slots and the given
81 * reclaim function is invoked successively for these. The reclaim
82 * function must, in addition to memory-managing the entry, return 0
83 * upon success and non-zero to veto the attempted pvector size
84 * change. The data argument is passed on to the reclaim function.
86 * The pvector_resize function returns 0 on success, with the size
87 * duly changed. Otherwise the function retains the current size and
88 * returns -index-1 for the index of the veto-ed entry.
91 pvector *pv, unsigned long new_size,
92 int (*reclaim)(pvector *pv,unsigned long index,void *item,void *data),
96 * Function: void **pvector_entry(pvector *pv,unsigned long index)
97 * \param pv - the pvector record
98 * \param index - the slot index
100 * [pgix,epix] = modulo( index, pv->page );
102 * \returns a direct pointer to the slot of the given index in the
103 * array, or 0 if the index is beyond the array limits (0-limit). Note
104 * that slot pointers are only valid while the pvector size is
107 extern void **pvector_entry(pvector *pv,unsigned long index);
110 * Function: unsigned long pvector_size(pvector *pv)
111 * \param pv - the pvector record
112 * \returns the size of the pvector.
114 inline unsigned long pvector_size(pvector *pv) {
118 void pvector_set(pvector *pv,unsigned long index,void *value);
120 void *pvector_get(pvector *pv,unsigned long index);
122 void pvector_append(pvector *pv,void *value);
124 void pvector_copy(pvector *dst,unsigned long di,
125 pvector *src,unsigned long si,unsigned long n);
127 void pvector_dump(pvector *pv,
128 int (*itemdump)(const unsigned long ,const void *));
130 void pvector_qsort(pvector *pv,int (*compar)(const void *,const void *));
132 void pvector_iterate(pvector *pv,
133 int (*itemfn)(unsigned long,void*,void*),