mcabber/libjabber/pool.c
author mikael
Wed, 06 Apr 2005 12:35:34 +0000
changeset 57 f381236239a4
parent 25 bf3d6e241714
child 414 ec86d759ed54
permissions -rw-r--r--
[/trunk] Changeset 72 by mikael * Switch to autoconf and automake.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
25
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     1
/*
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     2
 *  This program is free software; you can redistribute it and/or modify
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     3
 *  it under the terms of the GNU General Public License as published by
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     4
 *  the Free Software Foundation; either version 2 of the License, or
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     5
 *  (at your option) any later version.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     6
 *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     7
 *  This program is distributed in the hope that it will be useful,
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     8
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
     9
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    10
 *  GNU General Public License for more details.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    11
 *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    12
 *  You should have received a copy of the GNU General Public License
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    13
 *  along with this program; if not, write to the Free Software
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    14
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    15
 *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    16
 *  Jabber
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    17
 *  Copyright (C) 1998-1999 The Jabber Team http://jabber.org/
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    18
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    19
 *  2/27/00:3am, random plans by jer
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    20
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    21
 *  ok based on gprof, we really need some innovation here... my thoughs are this:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    22
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    23
 *  most things are strings, so have a string-based true-blue garbage collector
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    24
 *  one big global hash containing all the strings created by any pstrdup, returning const char *
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    25
 *  a refcount on each string block
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    26
 *  when a pool is freed, it moves down the refcount
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    27
 *  garbage collector collects pools on the free stack, and runs through the hash for unused strings
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    28
 *  j_strcmp can check for == (if they are both from a pstrdup)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    29
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    30
 *  let's see... this would change:
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    31
 *  pstrdup: do a hash lookup, success=return, fail=pmalloc & hash put
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    32
 *  pool_free: 
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    33
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    34
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    35
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    36
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    37
 *  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    38
 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    39
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    40
#include "libxode.h"
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    41
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    42
#ifdef POOL_DEBUG
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    43
int pool__total = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    44
int pool__ltotal = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    45
HASHTABLE pool__disturbed = NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    46
void *_pool__malloc(size_t size)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    47
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    48
    pool__total++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    49
    return malloc(size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    50
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    51
void _pool__free(void *block)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    52
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    53
    pool__total--;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    54
    free(block);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    55
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    56
#else
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    57
#define _pool__malloc malloc
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    58
#define _pool__free free
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    59
#endif
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    60
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    61
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    62
/* make an empty pool */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    63
pool _pool_new(char *zone)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    64
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    65
    pool p;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    66
    while((p = _pool__malloc(sizeof(_pool))) == NULL) sleep(1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    67
    p->cleanup = NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    68
    p->heap = NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    69
    p->size = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    70
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    71
#ifdef POOL_DEBUG
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    72
    p->lsize = -1;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    73
    p->zone[0] = '\0';
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    74
    strcat(p->zone,zone);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    75
    sprintf(p->name,"%X",p);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    76
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    77
    if(pool__disturbed == NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    78
	pool__disturbed = ghash_create(POOL_DEBUG,(KEYHASHFUNC)str_hash_code,(KEYCOMPAREFUNC)j_strcmp);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    79
    ghash_put(pool__disturbed,p->name,p);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    80
#endif
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    81
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    82
    return p;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    83
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    84
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    85
/* free a heap */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    86
void _pool_heap_free(void *arg)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    87
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    88
    struct pheap *h = (struct pheap *)arg;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    89
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    90
    _pool__free(h->block);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    91
    _pool__free(h);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    92
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    93
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    94
/* mem should always be freed last */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    95
void _pool_cleanup_append(pool p, struct pfree *pf)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    96
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    97
    struct pfree *cur;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    98
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
    99
    if(p->cleanup == NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   100
    {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   101
	p->cleanup = pf;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   102
	return;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   103
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   104
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   105
    /* fast forward to end of list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   106
    for(cur = p->cleanup; cur->next != NULL; cur = cur->next);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   107
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   108
    cur->next = pf;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   109
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   110
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   111
/* create a cleanup tracker */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   112
struct pfree *_pool_free(pool p, pool_cleaner f, void *arg)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   113
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   114
    struct pfree *ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   115
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   116
    /* make the storage for the tracker */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   117
    while((ret = _pool__malloc(sizeof(struct pfree))) == NULL) sleep(1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   118
    ret->f = f;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   119
    ret->arg = arg;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   120
    ret->next = NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   121
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   122
    return ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   123
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   124
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   125
/* create a heap and make sure it get's cleaned up */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   126
struct pheap *_pool_heap(pool p, int size)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   127
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   128
    struct pheap *ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   129
    struct pfree *clean;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   130
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   131
    /* make the return heap */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   132
    while((ret = _pool__malloc(sizeof(struct pheap))) == NULL) sleep(1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   133
    while((ret->block = _pool__malloc(size)) == NULL) sleep(1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   134
    ret->size = size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   135
    p->size += size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   136
    ret->used = 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   137
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   138
    /* append to the cleanup list */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   139
    clean = _pool_free(p, _pool_heap_free, (void *)ret);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   140
    clean->heap = ret; /* for future use in finding used mem for pstrdup */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   141
    _pool_cleanup_append(p, clean);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   142
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   143
    return ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   144
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   145
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   146
pool _pool_new_heap(int size, char *zone)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   147
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   148
    pool p;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   149
    p = _pool_new(zone);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   150
    p->heap = _pool_heap(p,size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   151
    return p;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   152
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   153
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   154
void *pmalloc(pool p, int size)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   155
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   156
    void *block;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   157
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   158
    if(p == NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   159
    {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   160
	fprintf(stderr,"Memory Leak! [pmalloc received NULL pool, unable to track allocation, exiting]\n");
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   161
	abort();
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   162
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   163
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   164
    /* if there is no heap for this pool or it's a big request, just raw, I like how we clean this :) */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   165
    if(p->heap == NULL || size > (p->heap->size / 2))
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   166
    {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   167
	while((block = _pool__malloc(size)) == NULL) sleep(1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   168
	p->size += size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   169
	_pool_cleanup_append(p, _pool_free(p, _pool__free, block));
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   170
	return block;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   171
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   172
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   173
    /* we have to preserve boundaries, long story :) */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   174
    if(size >= 4)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   175
	while(p->heap->used&7) p->heap->used++;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   176
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   177
    /* if we don't fit in the old heap, replace it */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   178
    if(size > (p->heap->size - p->heap->used))
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   179
	p->heap = _pool_heap(p, p->heap->size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   180
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   181
    /* the current heap has room */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   182
    block = (char *)p->heap->block + p->heap->used;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   183
    p->heap->used += size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   184
    return block;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   185
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   186
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   187
void *pmalloc_x(pool p, int size, char c)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   188
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   189
   void* result = pmalloc(p, size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   190
   if (result != NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   191
	   memset(result, c, size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   192
   return result;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   193
}  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   194
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   195
/* easy safety utility (for creating blank mem for structs, etc) */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   196
void *pmalloco(pool p, int size)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   197
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   198
    void *block = pmalloc(p, size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   199
    memset(block, 0, size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   200
    return block;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   201
}  
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   202
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   203
/* 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 */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   204
char *pstrdup(pool p, const char *src)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   205
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   206
    char *ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   207
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   208
    if(src == NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   209
	return NULL;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   210
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   211
    ret = pmalloc(p,strlen(src) + 1);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   212
    strcpy(ret,src);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   213
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   214
    return ret;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   215
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   216
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   217
/* when move above, this one would actually return a new block */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   218
char *pstrdupx(pool p, const char *src)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   219
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   220
    return pstrdup(p, src);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   221
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   222
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   223
int pool_size(pool p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   224
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   225
    if(p == NULL) return 0;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   226
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   227
    return p->size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   228
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   229
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   230
void pool_free(pool p)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   231
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   232
    struct pfree *cur, *stub;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   233
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   234
    if(p == NULL) return;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   235
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   236
    cur = p->cleanup;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   237
    while(cur != NULL)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   238
    {
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   239
	(*cur->f)(cur->arg);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   240
	stub = cur->next;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   241
	_pool__free(cur);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   242
	cur = stub;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   243
    }
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   244
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   245
#ifdef POOL_DEBUG
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   246
    ghash_remove(pool__disturbed,p->name);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   247
#endif
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   248
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   249
    _pool__free(p);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   250
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   251
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   252
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   253
/* public cleanup utils, insert in a way that they are run FIFO, before mem frees */
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   254
void pool_cleanup(pool p, pool_cleaner f, void *arg)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   255
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   256
    struct pfree *clean;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   257
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   258
    clean = _pool_free(p, f, arg);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   259
    clean->next = p->cleanup;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   260
    p->cleanup = clean;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   261
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   262
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   263
#ifdef POOL_DEBUG
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   264
void debug_log(char *zone, const char *msgfmt, ...);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   265
int _pool_stat(void *arg, const void *key, void *data)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   266
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   267
    pool p = (pool)data;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   268
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   269
    if(p->lsize == -1)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   270
	debug_log("leak","%s: %X is a new pool",p->zone,p->name);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   271
    else if(p->size > p->lsize)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   272
	debug_log("leak","%s: %X grew %d",p->zone,p->name, p->size - p->lsize);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   273
    else if((int)arg)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   274
	debug_log("leak","%s: %X exists %d",p->zone,p->name, p->size);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   275
    p->lsize = p->size;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   276
    return 1;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   277
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   278
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   279
void pool_stat(int full)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   280
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   281
    ghash_walk(pool__disturbed,_pool_stat,(void *)full);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   282
    if(pool__total != pool__ltotal)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   283
	debug_log("leak","%d\ttotal missed mallocs",pool__total);
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   284
    pool__ltotal = pool__total;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   285
    return;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   286
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   287
#else
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   288
void pool_stat(int full)
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   289
{
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   290
    return;
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   291
}
bf3d6e241714 [/trunk] Changeset 41 by mikael
mikael
parents:
diff changeset
   292
#endif