IPP Software Navigation Tools IPP Links Communication Pan-STARRS Links

Ignore:
Timestamp:
Jun 23, 2004, 1:00:17 PM (22 years ago)
Author:
desonia
Message:

Changed the means of deallocation of memory. ps_Alloc now registers an optional free function to handle any additional processing of a memory object.

Location:
trunk/psLib/src/sysUtils
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/psLib/src/sysUtils/psHash.c

    r964 r1073  
    1010 *  @author George Gusciora, MHPCC
    1111 *   
    12  *  @version $Revision: 1.8 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2004-06-10 00:09:55 $
     12 *  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2004-06-23 23:00:15 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    1818#include <stdio.h>
    1919#include <string.h>
     20#include <stdbool.h>
    2021#include "psHash.h"
    2122#include "psMemory.h"
     
    2425#include "psAbort.h"
    2526
     27static psHashBucket *hashBucketAlloc(const char *key,void *data,psHashBucket *next);
     28static void hashBucketFree(psHashBucket *bucket);
     29static void *doHashWork(psHash* table, const char* key, void* data, bool remove
     30                           );
     31static void hashFree(psHash *table);
    2632
    2733/******************************************************************************
     
    8793    // Allocate memory for the new hash bucket.
    8894    psHashBucket *bucket = psAlloc(sizeof(psHashBucket));
     95    p_psMemSetDeallocator(bucket,(psFreeFcn)hashBucketFree);
    8996
    9097    // Initialize the bucket.
     
    105112
    106113/******************************************************************************
    107 hashBucketFree(bucket, itemFree): This procedure deallocates the specified
    108 hash bucket.  If "itemFree" is NULL, then we simply free the data with the
    109 standard psFree() function.  If "itemFree" is not NULL, then it must be a
    110 function pointer which takes the hash bucket as a parameter, and frees the
    111 data in that hash bucket.
     114hashBucketFree(bucket): This procedure deallocates the specified
     115hash bucket. 
    112116Inputs:
    113117    bucket: the hash bucket to be freed.
    114     itemFree: a function pointer, possibly NULL.
    115118Return:
    116119    NONE
    117120 *****************************************************************************/
    118 static void hashBucketFree(psHashBucket *bucket,   // bucket to free
    119                            void (*itemFree)(void *item)) // how to free data;
    120 {
    121     if (bucket == NULL)
    122     {
     121static void hashBucketFree(psHashBucket *bucket)
     122{
     123    if (bucket == NULL) {
    123124        return;
    124125    }
     
    126127    // A bucket is actually a linked list of buckets.  We recursively step
    127128    // through that linked list, free each bucket.
    128     if (bucket->next != NULL)
    129     {
    130         hashBucketFree(bucket, itemFree);
    131     }
     129    psFree(bucket->next);
    132130
    133131    psFree(bucket->key);
    134     psMemDecrRefCounter(bucket->data);
    135 
    136     if (itemFree != NULL)
    137     {
    138         itemFree(bucket->data);
    139     } else
    140     {
    141         psFree(bucket->data);
    142     }
    143 
    144     psFree(bucket);
     132
     133    psFree(bucket->data);
    145134}
    146135
     
    159148    // Create the new hash table.
    160149    psHash *table = psAlloc(sizeof(psHash));
     150    p_psMemSetDeallocator(table,(psFreeFcn)hashFree);
    161151
    162152    // Allocate memory for the buckets.
     
    185175Inputs:
    186176    table: a hash table
    187     itemFree: a function pointer, possibly NULL.
    188177Return:
    189178    NONE
    190179 *****************************************************************************/
    191 void psHashFree(psHash *table,  // hash table to be freed
    192                 void (*itemFree)(void *item)) // how to free hashed data; or NULL
     180static void hashFree(psHash *table)
    193181{
    194182    psHashBucket *tmp = NULL;           // Used to step through linked list.
     
    196184    int i = 0;                          // Loop index variable.
    197185
    198     if (table == NULL)
    199     {
     186    if (table == NULL) {
    200187        return;
    201188    }
     
    204191    // NULL, then free the bucket via a function call to hashBucketFree();
    205192
    206     for (i = 0; i < table->nbucket; i++)
    207     {
     193    for (i = 0; i < table->nbucket; i++) {
    208194        // A bucket is composed of a linked list of buckets.  We use the
    209195        // "tmp" and "ptr" pointers to step through that list and free each
     
    214200            while (ptr != NULL) {
    215201                tmp = ptr->next;
    216                 hashBucketFree(ptr, itemFree);
     202                psFree(ptr);
    217203                ptr = tmp;
    218204            }
     
    222208    // Free the bucket structure, then the hash table.
    223209    psFree(table->buckets);
    224     psFree(table);
    225 }
    226 
    227 /******************************************************************************
    228 doHashWork(table, key, data, remove, itemFree): This is an internal
     210}
     211
     212/******************************************************************************
     213doHashWork(table, key, data, remove): This is an internal
    229214procedure which does the bulk of the work in using the hash table.  Depending
    230215upon the input parameters, it will either insert a new key/data into the hash
    231216table, retrieve the data for a specified key, or remove a key/data item.  If
    232 we try to insert a key that already exists in the hash table, then we call
    233 the user-supplied function itemfree (or psFree if that is NULL), to free the
    234 existing data/key item.
     217we try to insert a key that already exists in the hash table, then we deallocate
     218the existing data/key item.
    235219Inputs:
    236220    table: a hash table
     
    238222    data: the data to insert, if not NULL
    239223    remove: set to non-zero if the key/data should be removed from the table.
    240     itemFree: function pointer
    241224Return:
    242225    NONE
     
    246229there is little common code between those functions.
    247230  *****************************************************************************/
    248 static void *doHashWork(psHash     *table,   // table to insert in
    249                         const char *key,     // key to use
    250                         void       *data,    // data to insert, or (if NULL) retrieve/remove
    251                         int remove
    252                             ,          // remove the item from the list?
    253                             void (*itemFree)(void *item)) // how to free hashed data
     231static void *doHashWork(psHash *table, const char *key, void *data, bool remove
     232                           )
    254233{
    255234    long int hash = 1;                  // This will contain an integer value
     
    313292                    }
    314293
    315                     psFree(ptr->key);
    316294                    psFree(ptr);
    317295
    318296                    // By definition, the data associated with that key
    319297                    // must be returned, not freed.
    320                     return psMemDecrRefCounter(data);
     298                    return data;
    321299                }
    322300                optr = ptr;
     
    354332                // the new data was not inserted into the hash table.
    355333
    356                 if (itemFree == NULL) {
    357                     psFree(psMemDecrRefCounter(ptr->data));
    358                 } else {
    359                     itemFree(psMemDecrRefCounter(ptr->data));
    360                 }
     334                psFree(ptr->data);
    361335
    362336                ptr->data = psMemIncrRefCounter(data);
     
    385359    NONE
    386360 *****************************************************************************/
    387 void *psHashInsert(psHash *table,   // table to insert in
    388                    const char *key, // key to use
    389                    void *data,      // data to insert
    390                    void (*itemFree)(void *item)) // how to free hashed data;
     361void *psHashInsert(psHash *table, const char *key, void *data)
    391362{
    392363    if (table == NULL) {
     
    400371    }
    401372
    402     return doHashWork(table, key, data, 0, itemFree);
     373    return doHashWork(table, key, data, 0);
    403374}
    404375
     
    425396
    426397
    427     return doHashWork(table, key, NULL, 0, NULL);
     398    return doHashWork(table, key, NULL, 0);
    428399}
    429400
     
    438409    The data that was associated with that key.
    439410 *****************************************************************************/
    440 void *psHashRemove(psHash *table,   // table to lookup key in
    441                    const char *key, // key to lookup
    442                    void (*itemFree)(void *item)) // how to free hashed data;
     411void *psHashRemove(psHash *table, const char *key)
    443412{
    444413    if (table == NULL) {
     
    449418    }
    450419
    451     return doHashWork(table, key, NULL, 1, itemFree);
    452 }
     420    return doHashWork(table, key, NULL, 1);
     421}
  • trunk/psLib/src/sysUtils/psHash.d

    r1041 r1073  
    11psHash.o psHash.d : psHash.c psHash.h ../collections/psList.h \
    2   ../collections/psVector.h ../collections/psType.h \
    3   ../sysUtils/psMemory.h psString.h psTrace.h psAbort.h
     2  ../collections/psVector.h ../collections/psType.h psMemory.h psString.h \
     3  psTrace.h psAbort.h
  • trunk/psLib/src/sysUtils/psHash.h

    r1013 r1073  
    1010 *  @author George Gusciora, MHPCC
    1111 *   
    12  *  @version $Revision: 1.13 $ $Name: not supported by cvs2svn $
    13  *  @date $Date: 2004-06-12 05:50:01 $
     12 *  @version $Revision: 1.14 $ $Name: not supported by cvs2svn $
     13 *  @date $Date: 2004-06-23 23:00:15 $
    1414 *
    1515 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    4545                   );
    4646
    47 /// Free hash buckets from table.
    48 void psHashFree(psHash *table,               ///< hash table to be freed
    49                 void (*itemFree)(void *item) ///< how to free hashed data; or NULL
    50                );
    51 
    5247/// Insert entry into table.
    5348void *psHashInsert(psHash *table,               ///< table to insert in
    5449                   const char *key,             ///< key to use
    55                    void *data,                  ///< data to insert
    56                    void (*itemFree)(void *item) ///< how to free hashed data; or NULL
     50                   void *data                   ///< data to insert
    5751                  );
    5852
    5953/// Lookup key in table.
    60 void *psHashLookup(psHash *table, ///< table to lookup key in
    61                    const char *key ///< key to lookup
     54void *psHashLookup(psHash *table,      ///< table to lookup key in
     55                   const char *key     ///< key to lookup
    6256                  );
    6357
    6458/// Remove key from table.
    65 void *psHashRemove(psHash *table, ///< table to lookup key in
    66                    const char *key, ///< key to lookup
    67                    void (*itemFree)(void *item) ///< how to free hashed data; or NULL
     59void *psHashRemove(psHash *table,      ///< table to lookup key in
     60                   const char *key     ///< key to lookup
    6861                  );
    6962
  • trunk/psLib/src/sysUtils/psMemory.c

    r876 r1073  
    88 *  @author Robert Lupton, Princeton University
    99 *
    10  *  @version $Revision: 1.24 $ $Name: not supported by cvs2svn $
    11  *  @date $Date: 2004-06-04 23:46:48 $
     10 *  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
     11 *  @date $Date: 2004-06-23 23:00:15 $
    1212 *
    1313 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    3030static int checkMemBlock(const psMemBlock *m, const char* funcName);
    3131static psMemBlock *lastMemBlockAllocated = NULL;
    32 pthread_mutex_t  memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
    33 pthread_mutex_t  memIdMutex = PTHREAD_MUTEX_INITIALIZER;
     32static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER;
     33static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER;
    3434
    3535/**
     
    9696psMemoryId p_psMemFreeID = 0;   // notify user this block is freed
    9797
    98 psMemoryId psMemAllocateCallbackSetID(psMemoryId id) // set p_psMemAllocateID to id
     98psMemoryId psMemAllocateCallbackSetID(psMemoryId id)
    9999{
    100100    psMemoryId old = p_psMemAllocateID;
     
    104104}
    105105
    106 psMemoryId psMemFreeCallbackSetID(psMemoryId id)  // set p_psMemFreeID to id
     106psMemoryId psMemFreeCallbackSetID(psMemoryId id)
    107107{
    108108    psMemoryId old = p_psMemFreeID;
     
    184184#define ALIGNED(P) ((void *)((long)(P) & ~03) == (P))
    185185
    186 static int
    187 checkMemBlock(const psMemBlock *m,
    188               const char* funcName)
     186static int checkMemBlock(const psMemBlock *m, const char* funcName)
    189187{
    190188    // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked,
     
    260258
    261259    ptr->file = file;
     260    ptr->freeFcn = NULL;
    262261    *(unsigned int*)&ptr->lineno = lineno;
    263262    ptr->startblock = P_PS_MEMMAGIC;
     
    346345    if (checkMemBlock(ptr, __func__) != 0) {
    347346        memProblemCallback(ptr, file, lineno); // we may not own this block; don't free it
    348     }
    349 
    350     psMemDecrRefCounter(vptr);          // this handles the free, if required.
     347        return;
     348    }
     349
     350    (void)psMemDecrRefCounter(vptr);   // this handles the free, if required.
    351351}
    352352
     
    354354 * Check for memory leaks. Not production quality code
    355355 */
    356 int psMemCheckLeaks(
    357     psMemoryId id0,                     // don't list blocks with id < id0
    358     psMemBlock ***arr,                  // pointer to array of pointers to leaked blocks, or NULL
    359     FILE *fd)                           // print list of leaks to fd (or NULL)
     356int psMemCheckLeaks(psMemoryId id0,psMemBlock ***arr,FILE *fd)
    360357{
    361358    int nleak = 0;
     
    365362    pthread_mutex_lock(&memBlockListMutex);
    366363
    367     for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock)
    368     {
     364    for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {
    369365        if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {
    370366            nleak++;
     
    382378    pthread_mutex_unlock(&memBlockListMutex);
    383379
    384     if (nleak == 0 || arr == NULL)
    385     {
     380    if (nleak == 0 || arr == NULL) {
    386381        return nleak;
    387382    }
     
    390385    pthread_mutex_lock(&memBlockListMutex);
    391386
    392     for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock)
    393     {
     387    for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) {
    394388        if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) {
    395389            (*arr)[j++] = iter;
     
    408402 * Reference counting APIs
    409403 */
    410 psReferenceCount psMemGetRefCounter(void *vptr) // return refCounter
     404// return refCounter
     405psReferenceCount psMemGetRefCounter(void *vptr)
    411406{
    412407    psMemBlock *ptr;
    413408    unsigned int refCount;
    414409
    415     if (vptr == NULL)
    416     {
     410    if (vptr == NULL) {
    417411        return 0;
    418412    }
     
    420414    ptr = ((psMemBlock *)vptr) - 1;
    421415
    422     if (checkMemBlock(ptr, __func__) != 0)
    423     {
     416    if (checkMemBlock(ptr, __func__) != 0) {
    424417        memProblemCallback(ptr, __func__, __LINE__);
    425418    }
     
    431424    return refCount;
    432425}
    433 
    434 void *psMemIncrRefCounter(void *vptr) // increment and return refCounter
     426// increment and return refCounter
     427void *psMemIncrRefCounter(void *vptr)
    435428{
    436429    psMemBlock *ptr;
    437430
    438     if (vptr == NULL)
    439     {
     431    if (vptr == NULL) {
    440432        return vptr;
    441433    }
     
    443435    ptr = ((psMemBlock *)vptr) - 1;
    444436
    445     if (checkMemBlock(ptr, __func__))
    446     {
     437    if (checkMemBlock(ptr, __func__)) {
    447438        memProblemCallback(ptr, __func__, __LINE__);
    448439    }
     
    455446}
    456447
    457 void *psMemDecrRefCounter(void *vptr) // decrement and return refCounter
    458 {
    459     if (vptr == NULL)
    460     {
     448// decrement and return refCounter
     449void *psMemDecrRefCounter(void *vptr)
     450{
     451    if (vptr == NULL) {
    461452        return NULL;
    462453    }
     
    467458    pthread_mutex_lock(&ptr->refCounterMutex);
    468459
    469     if (ptr->refCounter > 1)
    470     {
     460    if (ptr->refCounter > 1) {
    471461        /// XXX - Probably should have another mutex here.
    472462        ptr->refCounter--;          // multiple references, just decrement the count.
    473463        pthread_mutex_unlock(&ptr->refCounterMutex);
    474464
    475     } else
    476     {
     465    } else {
    477466        pthread_mutex_unlock(&ptr->refCounterMutex);
    478467
     
    482471        }
    483472
     473        if (ptr->freeFcn != NULL) {
     474            ptr->freeFcn(vptr);
     475        }
     476
    484477        pthread_mutex_lock(&memBlockListMutex);
    485478
     
    507500}
    508501
    509 void p_psCustomFree(psFreeFcn fcn, void* ptr)
    510 {
    511 
    512     if (fcn == NULL) {
     502void p_psMemSetDeallocator(void* vptr, psFreeFcn freeFcn)
     503{
     504    if (vptr == NULL) {
    513505        return;
    514     } else {
    515         if (fcn == PS_FREE) {
    516             psFree(ptr);
    517         } else {
    518             fcn(ptr);
    519         }
    520     }
    521 }
     506    }
     507
     508    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
     509
     510    ptr->freeFcn = freeFcn;
     511
     512}
     513psFreeFcn p_psMemGetDeallocator(void* vptr)
     514{
     515    if (vptr == NULL) {
     516        return NULL;
     517    }
     518
     519    psMemBlock *ptr = ((psMemBlock *)vptr) - 1;
     520
     521    return ptr->freeFcn;
     522}
  • trunk/psLib/src/sysUtils/psMemory.h

    r978 r1073  
    1414 *  @ingroup MemoryManagement
    1515 *
    16  *  @version $Revision: 1.18 $ $Name: not supported by cvs2svn $
    17  *  @date $Date: 2004-06-10 02:09:57 $
     16 *  @version $Revision: 1.19 $ $Name: not supported by cvs2svn $
     17 *  @date $Date: 2004-06-23 23:00:15 $
    1818 *
    1919 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
     
    5050/// typedef for a memory block's reference count. Guaranteed to be some variety of integer.
    5151typedef unsigned long psReferenceCount;
     52
     53/// typedef for deallocator.
     54typedef void (*psFreeFcn)(void* ptr);
    5255
    5356/** Book-keeping data for storage allocator.
     
    5861typedef struct psMemBlock
    5962{
    60     const void* startblock;             ///< initialised to p_psMEMMAGIC
    61     struct psMemBlock* previousBlock;   ///< previous block in allocation list
    62     struct psMemBlock* nextBlock;       ///< next block allocation list
    63     size_t  userMemorySize;             ///< the size of the user-portion of the memory block
    64     const psMemoryId id;                ///< a unique ID for this allocation
    65     const char* file;                   ///< set from __FILE__ in e.g. p_psAlloc
    66     const int lineno;                   ///< set from __LINE__ in e.g. p_psAlloc
    67     pthread_mutex_t   refCounterMutex;  ///< mutex to ensure exclusive access to reference counter
    68     psReferenceCount refCounter;        ///< how many times pointer is referenced
    69     const void* endblock;               ///< initialised to p_psMEMMAGIC
     63    const void* startblock;            ///< initialised to p_psMEMMAGIC
     64    struct psMemBlock* previousBlock;  ///< previous block in allocation list
     65    struct psMemBlock* nextBlock;      ///< next block allocation list
     66    psFreeFcn freeFcn;                 ///< deallocator.  If NULL, use generic deallocation.
     67    size_t  userMemorySize;            ///< the size of the user-portion of the memory block
     68    const psMemoryId id;               ///< a unique ID for this allocation
     69    const char* file;                  ///< set from __FILE__ in e.g. p_psAlloc
     70    const int lineno;                  ///< set from __LINE__ in e.g. p_psAlloc
     71    pthread_mutex_t   refCounterMutex; ///< mutex to ensure exclusive access to reference counter
     72    psReferenceCount refCounter;       ///< how many times pointer is referenced
     73    const void* endblock;              ///< initialised to p_psMEMMAGIC
    7074}
    7175psMemBlock;
     
    114118);
    115119
    116 typedef void (*psFreeFcn)(void* ptr);
    117 
    118120/** Memory allocation.  This operates much like malloc(), but is guaranteed to return a non-NULL value.
    119121 *
    120122 *  @return void* pointer to the allocated buffer. This will not be NULL.
    121  *  @see psFree
     123 *  @see psFree 
    122124 */
    123125#ifdef DOXYGEN
     
    131133    int lineno                      ///< Line number of call
    132134);
     135
     136void p_psMemSetDeallocator(void* ptr, psFreeFcn freeFcn);
     137psFreeFcn p_psMemGetDeallocator(void* ptr);
     138
    133139/// Memory allocation. psAlloc sends file and line number to p_psAlloc.
    134140#define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__)
     
    282288);
    283289
    284 #define PS_FREE     (void*)1
    285 
    286290//@} End of Memory Management Functions
    287291
    288 
    289292#ifndef DOXYGEN
    290 
    291 void p_psCustomFree(psFreeFcn fcn,void* ptr);
    292293
    293294/*
Note: See TracChangeset for help on using the changeset viewer.