File Coverage

ext/arybase/ptable.h
Criterion Covered Total %
statement 21 46 45.7
branch n/a
condition n/a
subroutine n/a
total 21 46 45.7


line stmt bran cond sub time code
1           /* This is a pointer table implementation essentially copied from the ptr_table
2           * implementation in perl's sv.c, except that it has been modified to use memory
3           * shared across threads. */
4            
5           /* This header is designed to be included several times with different
6           * definitions for PTABLE_NAME and PTABLE_VAL_FREE(). */
7            
8           #undef pPTBLMS
9           #undef pPTBLMS_
10           #undef aPTBLMS
11           #undef aPTBLMS_
12            
13           /* Context for PerlMemShared_* functions */
14            
15           #ifdef PERL_IMPLICIT_SYS
16           # define pPTBLMS pTHX
17           # define pPTBLMS_ pTHX_
18           # define aPTBLMS aTHX
19           # define aPTBLMS_ aTHX_
20           #else
21           # define pPTBLMS
22           # define pPTBLMS_
23           # define aPTBLMS
24           # define aPTBLMS_
25           #endif
26            
27           #ifndef pPTBL
28           # define pPTBL pPTBLMS
29           #endif
30           #ifndef pPTBL_
31           # define pPTBL_ pPTBLMS_
32           #endif
33           #ifndef aPTBL
34           # define aPTBL aPTBLMS
35           #endif
36           #ifndef aPTBL_
37           # define aPTBL_ aPTBLMS_
38           #endif
39            
40           #ifndef PTABLE_NAME
41           # define PTABLE_NAME ptable
42           #endif
43            
44           #ifndef PTABLE_VAL_FREE
45           # define PTABLE_VAL_FREE(V)
46           #endif
47            
48           #ifndef PTABLE_JOIN
49           # define PTABLE_PASTE(A, B) A ## B
50           # define PTABLE_JOIN(A, B) PTABLE_PASTE(A, B)
51           #endif
52            
53           #ifndef PTABLE_PREFIX
54           # define PTABLE_PREFIX(X) PTABLE_JOIN(PTABLE_NAME, X)
55           #endif
56            
57           #ifndef ptable_ent
58           typedef struct ptable_ent {
59           struct ptable_ent *next;
60           const void * key;
61           void * val;
62           } ptable_ent;
63           #define ptable_ent ptable_ent
64           #endif /* !ptable_ent */
65            
66           #ifndef ptable
67           typedef struct ptable {
68           ptable_ent **ary;
69           UV max;
70           UV items;
71           } ptable;
72           #define ptable ptable
73           #endif /* !ptable */
74            
75           #ifndef ptable_new
76           STATIC ptable *ptable_new(pPTBLMS) {
77           #define ptable_new() ptable_new(aPTBLMS)
78 236         ptable *t = (ptable *)PerlMemShared_malloc(sizeof *t);
79 236         t->max = 63;
80 236         t->items = 0;
81 236         t->ary = (ptable_ent **)PerlMemShared_calloc(t->max + 1, sizeof *t->ary);
82           return t;
83           }
84           #endif /* !ptable_new */
85            
86           #ifndef PTABLE_HASH
87           # define PTABLE_HASH(ptr) \
88           ((PTR2UV(ptr) >> 3) ^ (PTR2UV(ptr) >> (3 + 7)) ^ (PTR2UV(ptr) >> (3 + 17)))
89           #endif
90            
91           #ifndef ptable_find
92 0         STATIC ptable_ent *ptable_find(const ptable * const t, const void * const key) {
93           #define ptable_find ptable_find
94           ptable_ent *ent;
95 3616         const UV hash = PTABLE_HASH(key);
96            
97 3616         ent = t->ary[hash & t->max];
98 96         for (; ent; ent = ent->next) {
99 390         if (ent->key == key)
100           return ent;
101           }
102            
103           return NULL;
104           }
105           #endif /* !ptable_find */
106            
107           #ifndef ptable_fetch
108           STATIC void *ptable_fetch(const ptable * const t, const void * const key) {
109           #define ptable_fetch ptable_fetch
110           const ptable_ent *const ent = ptable_find(t, key);
111            
112 568         return ent ? ent->val : NULL;
113           }
114           #endif /* !ptable_fetch */
115            
116           #ifndef ptable_split
117 0         STATIC void ptable_split(pPTBLMS_ ptable * const t) {
118           #define ptable_split(T) ptable_split(aPTBLMS_ (T))
119 0         ptable_ent **ary = t->ary;
120 0         const UV oldsize = t->max + 1;
121 0         UV newsize = oldsize * 2;
122           UV i;
123            
124 0         ary = (ptable_ent **)PerlMemShared_realloc(ary, newsize * sizeof(*ary));
125 0         Zero(&ary[oldsize], newsize - oldsize, sizeof(*ary));
126 0         t->max = --newsize;
127 0         t->ary = ary;
128            
129 0         for (i = 0; i < oldsize; i++, ary++) {
130           ptable_ent **curentp, **entp, *ent;
131 0         if (!*ary)
132 0         continue;
133 0         curentp = ary + oldsize;
134 0         for (entp = ary, ent = *ary; ent; ent = *entp) {
135 0         if ((newsize & PTABLE_HASH(ent->key)) != i) {
136 0         *entp = ent->next;
137 0         ent->next = *curentp;
138 0         *curentp = ent;
139 0         continue;
140           } else
141 0         entp = &ent->next;
142           }
143           }
144 0         }
145           #endif /* !ptable_split */
146            
147 3048         STATIC void PTABLE_PREFIX(_store)(pPTBL_ ptable * const t, const void * const key, void * const val) {
148           ptable_ent *ent = ptable_find(t, key);
149            
150 3048         if (ent) {
151 0         void *oldval = ent->val;
152 0         PTABLE_VAL_FREE(oldval);
153 0         ent->val = val;
154 3048         } else if (val) {
155 274         const UV i = PTABLE_HASH(key) & t->max;
156 274         ent = (ptable_ent *)PerlMemShared_malloc(sizeof *ent);
157 274         ent->key = key;
158 274         ent->val = val;
159 274         ent->next = t->ary[i];
160 274         t->ary[i] = ent;
161 274         t->items++;
162 274         if (ent->next && t->items > t->max)
163 0         ptable_split(t);
164           }
165 3048         }
166            
167           #ifndef ptable_walk
168           STATIC void ptable_walk(pTHX_ ptable * const t, void (*cb)(pTHX_ ptable_ent *ent, void *userdata), void *userdata) {
169           #define ptable_walk(T, CB, UD) ptable_walk(aTHX_ (T), (CB), (UD))
170           if (t && t->items) {
171           ptable_ent ** const array = t->ary;
172           UV i = t->max;
173           do {
174           ptable_ent *entry;
175           for (entry = array[i]; entry; entry = entry->next)
176           cb(aTHX_ entry, userdata);
177           } while (i--);
178           }
179           }
180           #endif /* !ptable_walk */
181            
182           STATIC void PTABLE_PREFIX(_clear)(pPTBL_ ptable * const t) {
183           if (t && t->items) {
184           ptable_ent ** const array = t->ary;
185           UV i = t->max;
186            
187           do {
188           ptable_ent *entry = array[i];
189           while (entry) {
190           ptable_ent * const oentry = entry;
191           void *val = oentry->val;
192           entry = entry->next;
193           PTABLE_VAL_FREE(val);
194           PerlMemShared_free(oentry);
195           }
196           array[i] = NULL;
197           } while (i--);
198            
199           t->items = 0;
200           }
201           }
202            
203           STATIC void PTABLE_PREFIX(_free)(pPTBL_ ptable * const t) {
204           if (!t)
205           return;
206           PTABLE_PREFIX(_clear)(aPTBL_ t);
207           PerlMemShared_free(t->ary);
208           PerlMemShared_free(t);
209           }
210            
211           #undef pPTBL
212           #undef pPTBL_
213           #undef aPTBL
214           #undef aPTBL_
215            
216           #undef PTABLE_NAME
217           #undef PTABLE_VAL_FREE