Mercurial > pidgin
annotate src/protocols/jabber/pool.c @ 6928:6ed0a1c045b4
[gaim-migrate @ 7475]
Added support for invisible plugins.
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Wed, 24 Sep 2003 01:28:33 +0000 |
parents | 988485669631 |
children |
rev | line source |
---|---|
3127 | 1 /* -------------------------------------------------------------------------- |
2 * | |
3 * License | |
4 * | |
5 * The contents of this file are subject to the Jabber Open Source License | |
6 * Version 1.0 (the "JOSL"). You may not copy or use this file, in either | |
7 * source code or executable form, except in compliance with the JOSL. You | |
8 * may obtain a copy of the JOSL at http://www.jabber.org/ or at | |
9 * http://www.opensource.org/. | |
2086 | 10 * |
3127 | 11 * Software distributed under the JOSL is distributed on an "AS IS" basis, |
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the JOSL | |
13 * for the specific language governing rights and limitations under the | |
14 * JOSL. | |
2086 | 15 * |
3127 | 16 * Copyrights |
17 * | |
18 * Portions created by or assigned to Jabber.com, Inc. are | |
19 * Copyright (c) 1999-2002 Jabber.com, Inc. All Rights Reserved. Contact | |
20 * information for Jabber.com, Inc. is available at http://www.jabber.com/. | |
2086 | 21 * |
3127 | 22 * Portions Copyright (c) 1998-1999 Jeremie Miller. |
23 * | |
24 * Acknowledgements | |
25 * | |
26 * Special thanks to the Jabber Open Source Contributors for their | |
27 * suggestions and support of Jabber. | |
28 * | |
29 * Alternatively, the contents of this file may be used under the terms of the | |
30 * GNU General Public License Version 2 or later (the "GPL"), in which case | |
31 * the provisions of the GPL are applicable instead of those above. If you | |
32 * wish to allow use of your version of this file only under the terms of the | |
33 * GPL and not to allow others to use your version of this file under the JOSL, | |
34 * indicate your decision by deleting the provisions above and replace them | |
35 * with the notice and other provisions required by the GPL. If you do not | |
36 * delete the provisions above, a recipient may use your version of this file | |
37 * under either the JOSL or the GPL. | |
38 * | |
39 * | |
40 * --------------------------------------------------------------------------*/ | |
2086 | 41 |
3127 | 42 #include "lib.h" |
2086 | 43 |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3127
diff
changeset
|
44 #ifdef _WIN32 |
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3127
diff
changeset
|
45 #include "win32dep.h" |
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3127
diff
changeset
|
46 #endif |
2086 | 47 |
48 #ifdef POOL_DEBUG | |
49 int pool__total = 0; | |
50 int pool__ltotal = 0; | |
51 HASHTABLE pool__disturbed = NULL; | |
52 void *_pool__malloc(size_t size) | |
53 { | |
54 pool__total++; | |
55 return malloc(size); | |
56 } | |
57 void _pool__free(void *block) | |
58 { | |
59 pool__total--; | |
60 free(block); | |
61 } | |
62 #else | |
63 #define _pool__malloc malloc | |
64 #define _pool__free free | |
65 #endif | |
66 | |
67 | |
68 /* make an empty pool */ | |
69 pool _pool_new(char *zone) | |
70 { | |
71 pool p; | |
72 while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1); | |
73 p->cleanup = NULL; | |
74 p->heap = NULL; | |
75 p->size = 0; | |
76 | |
77 #ifdef POOL_DEBUG | |
78 p->lsize = -1; | |
79 p->zone[0] = '\0'; | |
80 strcat(p->zone,zone); | |
81 sprintf(p->name,"%X",p); | |
82 | |
83 if(pool__disturbed == NULL) | |
3127 | 84 { |
85 pool__disturbed = 1; /* reentrancy flag! */ | |
2086 | 86 pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp); |
3127 | 87 } |
88 if(pool__disturbed != 1) | |
89 ghash_put(pool__disturbed,p->name,p); | |
2086 | 90 #endif |
91 | |
92 return p; | |
93 } | |
94 | |
95 /* free a heap */ | |
96 void _pool_heap_free(void *arg) | |
97 { | |
98 struct pheap *h = (struct pheap *)arg; | |
99 | |
100 _pool__free(h->block); | |
101 _pool__free(h); | |
102 } | |
103 | |
104 /* mem should always be freed last */ | |
105 void _pool_cleanup_append(pool p, struct pfree *pf) | |
106 { | |
107 struct pfree *cur; | |
108 | |
109 if(p->cleanup == NULL) | |
110 { | |
111 p->cleanup = pf; | |
112 return; | |
113 } | |
114 | |
115 /* fast forward to end of list */ | |
116 for(cur = p->cleanup; cur->next != NULL; cur = cur->next); | |
117 | |
118 cur->next = pf; | |
119 } | |
120 | |
121 /* create a cleanup tracker */ | |
122 struct pfree *_pool_free(pool p, pool_cleaner f, void *arg) | |
123 { | |
124 struct pfree *ret; | |
125 | |
126 /* make the storage for the tracker */ | |
127 while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1); | |
128 ret->f = f; | |
129 ret->arg = arg; | |
130 ret->next = NULL; | |
131 | |
132 return ret; | |
133 } | |
134 | |
135 /* create a heap and make sure it get's cleaned up */ | |
136 struct pheap *_pool_heap(pool p, int size) | |
137 { | |
138 struct pheap *ret; | |
139 struct pfree *clean; | |
140 | |
141 /* make the return heap */ | |
142 while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1); | |
143 while((ret->block = _pool__malloc(size)) == NULL) sleep(1); | |
144 ret->size = size; | |
145 p->size += size; | |
146 ret->used = 0; | |
147 | |
148 /* append to the cleanup list */ | |
149 clean = _pool_free(p, _pool_heap_free, (void *)ret); | |
150 clean->heap = ret; /* for future use in finding used mem for pstrdup */ | |
151 _pool_cleanup_append(p, clean); | |
152 | |
153 return ret; | |
154 } | |
155 | |
156 pool _pool_new_heap(int size, char *zone) | |
157 { | |
158 pool p; | |
159 p = _pool_new(zone); | |
160 p->heap = _pool_heap(p,size); | |
161 return p; | |
162 } | |
163 | |
164 void *pmalloc(pool p, int size) | |
165 { | |
166 void *block; | |
167 | |
168 if(p == NULL) | |
169 { | |
170 fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n"); | |
171 abort(); | |
172 } | |
173 | |
174 /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */ | |
175 if(p->heap == NULL || size > (p->heap->size / 2)) | |
176 { | |
177 while((block = _pool__malloc(size)) == NULL) sleep(1); | |
178 p->size += size; | |
179 _pool_cleanup_append(p, _pool_free(p, _pool__free, block)); | |
180 return block; | |
181 } | |
182 | |
183 /* we have to preserve boundaries, long story :) */ | |
184 if(size >= 4) | |
185 while(p->heap->used&7) p->heap->used++; | |
186 | |
187 /* if we don't fit in the old heap, replace it */ | |
188 if(size > (p->heap->size - p->heap->used)) | |
189 p->heap = _pool_heap(p, p->heap->size); | |
190 | |
191 /* the current heap has room */ | |
192 block = (char *)p->heap->block + p->heap->used; | |
193 p->heap->used += size; | |
194 return block; | |
195 } | |
196 | |
197 void *pmalloc_x(pool p, int size, char c) | |
198 { | |
199 void* result = pmalloc(p, size); | |
200 if (result != NULL) | |
201 memset(result, c, size); | |
202 return result; | |
203 } | |
204 | |
205 /* easy safety utility (for creating blank mem for structs, etc) */ | |
206 void *pmalloco(pool p, int size) | |
207 { | |
208 void *block = pmalloc(p, size); | |
209 memset(block, 0, size); | |
210 return block; | |
211 } | |
212 | |
213 /* XXX efficient: move this to const char * and then loop throug the existing heaps to see if src is within a block in this pool */ | |
214 char *pstrdup(pool p, const char *src) | |
215 { | |
216 char *ret; | |
217 | |
218 if(src == NULL) | |
219 return NULL; | |
220 | |
221 ret = pmalloc(p,strlen(src) + 1); | |
222 strcpy(ret,src); | |
223 | |
224 return ret; | |
225 } | |
226 | |
227 /* when move above, this one would actually return a new block */ | |
228 char *pstrdupx(pool p, const char *src) | |
229 { | |
230 return pstrdup(p, src); | |
231 } | |
232 | |
233 int pool_size(pool p) | |
234 { | |
235 if(p == NULL) return 0; | |
236 | |
237 return p->size; | |
238 } | |
239 | |
240 void pool_free(pool p) | |
241 { | |
242 struct pfree *cur, *stub; | |
243 | |
244 if(p == NULL) return; | |
245 | |
246 cur = p->cleanup; | |
247 while(cur != NULL) | |
248 { | |
249 (*cur->f)(cur->arg); | |
250 stub = cur->next; | |
251 _pool__free(cur); | |
252 cur = stub; | |
253 } | |
254 | |
255 #ifdef POOL_DEBUG | |
256 ghash_remove(pool__disturbed,p->name); | |
257 #endif | |
258 | |
259 _pool__free(p); | |
260 | |
261 } | |
262 | |
263 /* public cleanup utils, insert in a way that they are run FIFO, before mem frees */ | |
264 void pool_cleanup(pool p, pool_cleaner f, void *arg) | |
265 { | |
266 struct pfree *clean; | |
267 | |
268 clean = _pool_free(p, f, arg); | |
269 clean->next = p->cleanup; | |
270 p->cleanup = clean; | |
271 } | |
272 | |
273 #ifdef POOL_DEBUG | |
274 void debug_log(char *zone, const char *msgfmt, ...); | |
275 int _pool_stat(void *arg, const void *key, void *data) | |
276 { | |
277 pool p = (pool)data; | |
278 | |
279 if(p->lsize == -1) | |
280 debug_log("leak","%s: %X is a new pool",p->zone,p->name); | |
281 else if(p->size > p->lsize) | |
282 debug_log("leak","%s: %X grew %d",p->zone,p->name, p->size - p->lsize); | |
283 else if((int)arg) | |
284 debug_log("leak","%s: %X exists %d",p->zone,p->name, p->size); | |
285 p->lsize = p->size; | |
286 return 1; | |
287 } | |
288 | |
289 void pool_stat(int full) | |
290 { | |
291 ghash_walk(pool__disturbed,_pool_stat,(void *)full); | |
292 if(pool__total != pool__ltotal) | |
293 debug_log("leak","%d\ttotal missed mallocs",pool__total); | |
294 pool__ltotal = pool__total; | |
295 return; | |
296 } | |
297 #else | |
298 void pool_stat(int full) | |
299 { | |
300 return; | |
301 } | |
302 #endif |