source: protocols/jabber/pool.c @ 7c0a497

Last change on this file since 7c0a497 was b7d3cc34, checked in by Wilmer van der Gaast <wilmer@…>, at 2005-11-06T18:23:18Z

Initial repository (0.99 release tree)

  • Property mode set to 100644
File size: 6.2 KB
Line 
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/. 
10 *
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.
15 *
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/.
21 *
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 * --------------------------------------------------------------------------*/
41
42#include "jabber.h"
43#include "bitlbee.h"
44#include <glib.h>
45
46
47#ifdef POOL_DEBUG
48int pool__total = 0;
49int pool__ltotal = 0;
50HASHTABLE pool__disturbed = NULL;
51void *_pool__malloc(size_t size)
52{
53    pool__total++;
54    return g_malloc(size);
55}
56void _pool__free(void *block)
57{
58    pool__total--;
59    g_free(block);
60}
61#else
62#define _pool__malloc g_malloc
63#define _pool__free g_free
64#endif
65
66
67/* make an empty pool */
68pool _pool_new(char *zone)
69{
70    pool p;
71    while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
72    p->cleanup = NULL;
73    p->heap = NULL;
74    p->size = 0;
75
76#ifdef POOL_DEBUG
77    p->lsize = -1;
78    p->zone[0] = '\0';
79    strcat(p->zone,zone);
80    sprintf(p->name,"%X",p);
81
82    if(pool__disturbed == NULL)
83    {
84        pool__disturbed = 1; /* reentrancy flag! */
85        pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp);
86    }
87    if(pool__disturbed != 1)
88        ghash_put(pool__disturbed,p->name,p);
89#endif
90
91    return p;
92}
93
94/* free a heap */
95static void _pool_heap_free(void *arg)
96{
97    struct pheap *h = (struct pheap *)arg;
98
99    _pool__free(h->block);
100    _pool__free(h);
101}
102
103/* mem should always be freed last */
104static void _pool_cleanup_append(pool p, struct pfree *pf)
105{
106    struct pfree *cur;
107
108    if(p->cleanup == NULL)
109    {
110        p->cleanup = pf;
111        return;
112    }
113
114    /* fast forward to end of list */
115    for(cur = p->cleanup; cur->next != NULL; cur = cur->next);
116
117    cur->next = pf;
118}
119
120/* create a cleanup tracker */
121static struct pfree *_pool_free(pool p, pool_cleaner f, void *arg)
122{
123    struct pfree *ret;
124
125    /* make the storage for the tracker */
126    while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
127    ret->f = f;
128    ret->arg = arg;
129    ret->next = NULL;
130
131    return ret;
132}
133
134/* create a heap and make sure it get's cleaned up */
135static struct pheap *_pool_heap(pool p, int size)
136{
137    struct pheap *ret;
138    struct pfree *clean;
139
140    /* make the return heap */
141    while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1);
142    while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
143    ret->size = size;
144    p->size += size;
145    ret->used = 0;
146
147    /* append to the cleanup list */
148    clean = _pool_free(p, _pool_heap_free, (void *)ret);
149    clean->heap = ret; /* for future use in finding used mem for pstrdup */
150    _pool_cleanup_append(p, clean);
151
152    return ret;
153}
154
155pool _pool_new_heap(int size, char *zone)
156{
157    pool p;
158    p = _pool_new(zone);
159    p->heap = _pool_heap(p,size);
160    return p;
161}
162
163void *pmalloc(pool p, int size)
164{
165    void *block;
166
167    if(p == NULL)
168    {
169        fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
170        abort();
171    }
172
173    /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */
174    if(p->heap == NULL || size > (p->heap->size / 2))
175    {
176        while((block = _pool__malloc(size)) == NULL) sleep(1);
177        p->size += size;
178        _pool_cleanup_append(p, _pool_free(p, _pool__free, block));
179        return block;
180    }
181
182    /* we have to preserve boundaries, long story :) */
183    if(size >= 4)
184        while(p->heap->used&7) p->heap->used++;
185
186    /* if we don't fit in the old heap, replace it */
187    if(size > (p->heap->size - p->heap->used))
188        p->heap = _pool_heap(p, p->heap->size);
189
190    /* the current heap has room */
191    block = (char *)p->heap->block + p->heap->used;
192    p->heap->used += size;
193    return block;
194}
195
196void *pmalloc_x(pool p, int size, char c)
197{
198   void* result = pmalloc(p, size);
199   if (result != NULL)
200           memset(result, c, size);
201   return result;
202} 
203
204/* easy safety utility (for creating blank mem for structs, etc) */
205void *pmalloco(pool p, int size)
206{
207    void *block = pmalloc(p, size);
208    memset(block, 0, size);
209    return block;
210} 
211
212/* 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 */
213char *pstrdup(pool p, const char *src)
214{
215    char *ret;
216
217    if(src == NULL)
218        return NULL;
219
220    ret = pmalloc(p,strlen(src) + 1);
221    strcpy(ret,src);
222
223    return ret;
224}
225
226void pool_free(pool p)
227{
228    struct pfree *cur, *stub;
229
230    if(p == NULL) return;
231
232    cur = p->cleanup;
233    while(cur != NULL)
234    {
235        (*cur->f)(cur->arg);
236        stub = cur->next;
237        _pool__free(cur);
238        cur = stub;
239    }
240
241#ifdef POOL_DEBUG
242    ghash_remove(pool__disturbed,p->name);
243#endif
244
245    _pool__free(p);
246
247}
Note: See TracBrowser for help on using the repository browser.