Changeset 1073 for trunk/psLib/src/sysUtils
- Timestamp:
- Jun 23, 2004, 1:00:17 PM (22 years ago)
- Location:
- trunk/psLib/src/sysUtils
- Files:
-
- 5 edited
-
psHash.c (modified) (21 diffs)
-
psHash.d (modified) (1 diff)
-
psHash.h (modified) (2 diffs)
-
psMemory.c (modified) (19 diffs)
-
psMemory.h (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/sysUtils/psHash.c
r964 r1073 10 10 * @author George Gusciora, MHPCC 11 11 * 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 $ 14 14 * 15 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 18 18 #include <stdio.h> 19 19 #include <string.h> 20 #include <stdbool.h> 20 21 #include "psHash.h" 21 22 #include "psMemory.h" … … 24 25 #include "psAbort.h" 25 26 27 static psHashBucket *hashBucketAlloc(const char *key,void *data,psHashBucket *next); 28 static void hashBucketFree(psHashBucket *bucket); 29 static void *doHashWork(psHash* table, const char* key, void* data, bool remove 30 ); 31 static void hashFree(psHash *table); 26 32 27 33 /****************************************************************************** … … 87 93 // Allocate memory for the new hash bucket. 88 94 psHashBucket *bucket = psAlloc(sizeof(psHashBucket)); 95 p_psMemSetDeallocator(bucket,(psFreeFcn)hashBucketFree); 89 96 90 97 // Initialize the bucket. … … 105 112 106 113 /****************************************************************************** 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. 114 hashBucketFree(bucket): This procedure deallocates the specified 115 hash bucket. 112 116 Inputs: 113 117 bucket: the hash bucket to be freed. 114 itemFree: a function pointer, possibly NULL.115 118 Return: 116 119 NONE 117 120 *****************************************************************************/ 118 static void hashBucketFree(psHashBucket *bucket, // bucket to free 119 void (*itemFree)(void *item)) // how to free data; 120 { 121 if (bucket == NULL) 122 { 121 static void hashBucketFree(psHashBucket *bucket) 122 { 123 if (bucket == NULL) { 123 124 return; 124 125 } … … 126 127 // A bucket is actually a linked list of buckets. We recursively step 127 128 // through that linked list, free each bucket. 128 if (bucket->next != NULL) 129 { 130 hashBucketFree(bucket, itemFree); 131 } 129 psFree(bucket->next); 132 130 133 131 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); 145 134 } 146 135 … … 159 148 // Create the new hash table. 160 149 psHash *table = psAlloc(sizeof(psHash)); 150 p_psMemSetDeallocator(table,(psFreeFcn)hashFree); 161 151 162 152 // Allocate memory for the buckets. … … 185 175 Inputs: 186 176 table: a hash table 187 itemFree: a function pointer, possibly NULL.188 177 Return: 189 178 NONE 190 179 *****************************************************************************/ 191 void psHashFree(psHash *table, // hash table to be freed 192 void (*itemFree)(void *item)) // how to free hashed data; or NULL 180 static void hashFree(psHash *table) 193 181 { 194 182 psHashBucket *tmp = NULL; // Used to step through linked list. … … 196 184 int i = 0; // Loop index variable. 197 185 198 if (table == NULL) 199 { 186 if (table == NULL) { 200 187 return; 201 188 } … … 204 191 // NULL, then free the bucket via a function call to hashBucketFree(); 205 192 206 for (i = 0; i < table->nbucket; i++) 207 { 193 for (i = 0; i < table->nbucket; i++) { 208 194 // A bucket is composed of a linked list of buckets. We use the 209 195 // "tmp" and "ptr" pointers to step through that list and free each … … 214 200 while (ptr != NULL) { 215 201 tmp = ptr->next; 216 hashBucketFree(ptr, itemFree);202 psFree(ptr); 217 203 ptr = tmp; 218 204 } … … 222 208 // Free the bucket structure, then the hash table. 223 209 psFree(table->buckets); 224 psFree(table); 225 } 226 227 /****************************************************************************** 228 doHashWork(table, key, data, remove, itemFree): This is an internal 210 } 211 212 /****************************************************************************** 213 doHashWork(table, key, data, remove): This is an internal 229 214 procedure which does the bulk of the work in using the hash table. Depending 230 215 upon the input parameters, it will either insert a new key/data into the hash 231 216 table, 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. 217 we try to insert a key that already exists in the hash table, then we deallocate 218 the existing data/key item. 235 219 Inputs: 236 220 table: a hash table … … 238 222 data: the data to insert, if not NULL 239 223 remove: set to non-zero if the key/data should be removed from the table. 240 itemFree: function pointer241 224 Return: 242 225 NONE … … 246 229 there is little common code between those functions. 247 230 *****************************************************************************/ 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 231 static void *doHashWork(psHash *table, const char *key, void *data, bool remove 232 ) 254 233 { 255 234 long int hash = 1; // This will contain an integer value … … 313 292 } 314 293 315 psFree(ptr->key);316 294 psFree(ptr); 317 295 318 296 // By definition, the data associated with that key 319 297 // must be returned, not freed. 320 return psMemDecrRefCounter(data);298 return data; 321 299 } 322 300 optr = ptr; … … 354 332 // the new data was not inserted into the hash table. 355 333 356 if (itemFree == NULL) { 357 psFree(psMemDecrRefCounter(ptr->data)); 358 } else { 359 itemFree(psMemDecrRefCounter(ptr->data)); 360 } 334 psFree(ptr->data); 361 335 362 336 ptr->data = psMemIncrRefCounter(data); … … 385 359 NONE 386 360 *****************************************************************************/ 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; 361 void *psHashInsert(psHash *table, const char *key, void *data) 391 362 { 392 363 if (table == NULL) { … … 400 371 } 401 372 402 return doHashWork(table, key, data, 0 , itemFree);373 return doHashWork(table, key, data, 0); 403 374 } 404 375 … … 425 396 426 397 427 return doHashWork(table, key, NULL, 0 , NULL);398 return doHashWork(table, key, NULL, 0); 428 399 } 429 400 … … 438 409 The data that was associated with that key. 439 410 *****************************************************************************/ 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; 411 void *psHashRemove(psHash *table, const char *key) 443 412 { 444 413 if (table == NULL) { … … 449 418 } 450 419 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 1 1 psHash.o psHash.d : psHash.c psHash.h ../collections/psList.h \ 2 ../collections/psVector.h ../collections/psType.h \3 ../sysUtils/psMemory.h psString.hpsTrace.h psAbort.h2 ../collections/psVector.h ../collections/psType.h psMemory.h psString.h \ 3 psTrace.h psAbort.h -
trunk/psLib/src/sysUtils/psHash.h
r1013 r1073 10 10 * @author George Gusciora, MHPCC 11 11 * 12 * @version $Revision: 1.1 3$ $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 $ 14 14 * 15 15 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 45 45 ); 46 46 47 /// Free hash buckets from table.48 void psHashFree(psHash *table, ///< hash table to be freed49 void (*itemFree)(void *item) ///< how to free hashed data; or NULL50 );51 52 47 /// Insert entry into table. 53 48 void *psHashInsert(psHash *table, ///< table to insert in 54 49 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 57 51 ); 58 52 59 53 /// Lookup key in table. 60 void *psHashLookup(psHash *table, ///< table to lookup key in61 const char *key ///< key to lookup54 void *psHashLookup(psHash *table, ///< table to lookup key in 55 const char *key ///< key to lookup 62 56 ); 63 57 64 58 /// 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 59 void *psHashRemove(psHash *table, ///< table to lookup key in 60 const char *key ///< key to lookup 68 61 ); 69 62 -
trunk/psLib/src/sysUtils/psMemory.c
r876 r1073 8 8 * @author Robert Lupton, Princeton University 9 9 * 10 * @version $Revision: 1.2 4$ $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 $ 12 12 * 13 13 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 30 30 static int checkMemBlock(const psMemBlock *m, const char* funcName); 31 31 static psMemBlock *lastMemBlockAllocated = NULL; 32 pthread_mutex_tmemBlockListMutex = PTHREAD_MUTEX_INITIALIZER;33 pthread_mutex_tmemIdMutex = PTHREAD_MUTEX_INITIALIZER;32 static pthread_mutex_t memBlockListMutex = PTHREAD_MUTEX_INITIALIZER; 33 static pthread_mutex_t memIdMutex = PTHREAD_MUTEX_INITIALIZER; 34 34 35 35 /** … … 96 96 psMemoryId p_psMemFreeID = 0; // notify user this block is freed 97 97 98 psMemoryId psMemAllocateCallbackSetID(psMemoryId id) // set p_psMemAllocateID to id98 psMemoryId psMemAllocateCallbackSetID(psMemoryId id) 99 99 { 100 100 psMemoryId old = p_psMemAllocateID; … … 104 104 } 105 105 106 psMemoryId psMemFreeCallbackSetID(psMemoryId id) // set p_psMemFreeID to id106 psMemoryId psMemFreeCallbackSetID(psMemoryId id) 107 107 { 108 108 psMemoryId old = p_psMemFreeID; … … 184 184 #define ALIGNED(P) ((void *)((long)(P) & ~03) == (P)) 185 185 186 static int 187 checkMemBlock(const psMemBlock *m, 188 const char* funcName) 186 static int checkMemBlock(const psMemBlock *m, const char* funcName) 189 187 { 190 188 // n.b. since this is called by psMemCheckCorruption while the memblock list is mutex locked, … … 260 258 261 259 ptr->file = file; 260 ptr->freeFcn = NULL; 262 261 *(unsigned int*)&ptr->lineno = lineno; 263 262 ptr->startblock = P_PS_MEMMAGIC; … … 346 345 if (checkMemBlock(ptr, __func__) != 0) { 347 346 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. 351 351 } 352 352 … … 354 354 * Check for memory leaks. Not production quality code 355 355 */ 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) 356 int psMemCheckLeaks(psMemoryId id0,psMemBlock ***arr,FILE *fd) 360 357 { 361 358 int nleak = 0; … … 365 362 pthread_mutex_lock(&memBlockListMutex); 366 363 367 for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) 368 { 364 for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) { 369 365 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) { 370 366 nleak++; … … 382 378 pthread_mutex_unlock(&memBlockListMutex); 383 379 384 if (nleak == 0 || arr == NULL) 385 { 380 if (nleak == 0 || arr == NULL) { 386 381 return nleak; 387 382 } … … 390 385 pthread_mutex_lock(&memBlockListMutex); 391 386 392 for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) 393 { 387 for (psMemBlock* iter = topBlock; iter != NULL; iter=iter->nextBlock) { 394 388 if ( (psMemGetRefCounter(iter+1) > 0) && (iter->id >= id0) ) { 395 389 (*arr)[j++] = iter; … … 408 402 * Reference counting APIs 409 403 */ 410 psReferenceCount psMemGetRefCounter(void *vptr) // return refCounter 404 // return refCounter 405 psReferenceCount psMemGetRefCounter(void *vptr) 411 406 { 412 407 psMemBlock *ptr; 413 408 unsigned int refCount; 414 409 415 if (vptr == NULL) 416 { 410 if (vptr == NULL) { 417 411 return 0; 418 412 } … … 420 414 ptr = ((psMemBlock *)vptr) - 1; 421 415 422 if (checkMemBlock(ptr, __func__) != 0) 423 { 416 if (checkMemBlock(ptr, __func__) != 0) { 424 417 memProblemCallback(ptr, __func__, __LINE__); 425 418 } … … 431 424 return refCount; 432 425 } 433 434 void *psMemIncrRefCounter(void *vptr) // increment and return refCounter426 // increment and return refCounter 427 void *psMemIncrRefCounter(void *vptr) 435 428 { 436 429 psMemBlock *ptr; 437 430 438 if (vptr == NULL) 439 { 431 if (vptr == NULL) { 440 432 return vptr; 441 433 } … … 443 435 ptr = ((psMemBlock *)vptr) - 1; 444 436 445 if (checkMemBlock(ptr, __func__)) 446 { 437 if (checkMemBlock(ptr, __func__)) { 447 438 memProblemCallback(ptr, __func__, __LINE__); 448 439 } … … 455 446 } 456 447 457 void *psMemDecrRefCounter(void *vptr)// decrement and return refCounter458 { 459 if (vptr == NULL) 460 {448 // decrement and return refCounter 449 void *psMemDecrRefCounter(void *vptr) 450 { 451 if (vptr == NULL) { 461 452 return NULL; 462 453 } … … 467 458 pthread_mutex_lock(&ptr->refCounterMutex); 468 459 469 if (ptr->refCounter > 1) 470 { 460 if (ptr->refCounter > 1) { 471 461 /// XXX - Probably should have another mutex here. 472 462 ptr->refCounter--; // multiple references, just decrement the count. 473 463 pthread_mutex_unlock(&ptr->refCounterMutex); 474 464 475 } else 476 { 465 } else { 477 466 pthread_mutex_unlock(&ptr->refCounterMutex); 478 467 … … 482 471 } 483 472 473 if (ptr->freeFcn != NULL) { 474 ptr->freeFcn(vptr); 475 } 476 484 477 pthread_mutex_lock(&memBlockListMutex); 485 478 … … 507 500 } 508 501 509 void p_psCustomFree(psFreeFcn fcn, void* ptr) 510 { 511 512 if (fcn == NULL) { 502 void p_psMemSetDeallocator(void* vptr, psFreeFcn freeFcn) 503 { 504 if (vptr == NULL) { 513 505 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 } 513 psFreeFcn 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 14 14 * @ingroup MemoryManagement 15 15 * 16 * @version $Revision: 1.1 8$ $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 $ 18 18 * 19 19 * Copyright 2004 Maui High Performance Computing Center, University of Hawaii … … 50 50 /// typedef for a memory block's reference count. Guaranteed to be some variety of integer. 51 51 typedef unsigned long psReferenceCount; 52 53 /// typedef for deallocator. 54 typedef void (*psFreeFcn)(void* ptr); 52 55 53 56 /** Book-keeping data for storage allocator. … … 58 61 typedef struct psMemBlock 59 62 { 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 70 74 } 71 75 psMemBlock; … … 114 118 ); 115 119 116 typedef void (*psFreeFcn)(void* ptr);117 118 120 /** Memory allocation. This operates much like malloc(), but is guaranteed to return a non-NULL value. 119 121 * 120 122 * @return void* pointer to the allocated buffer. This will not be NULL. 121 * @see psFree 123 * @see psFree 122 124 */ 123 125 #ifdef DOXYGEN … … 131 133 int lineno ///< Line number of call 132 134 ); 135 136 void p_psMemSetDeallocator(void* ptr, psFreeFcn freeFcn); 137 psFreeFcn p_psMemGetDeallocator(void* ptr); 138 133 139 /// Memory allocation. psAlloc sends file and line number to p_psAlloc. 134 140 #define psAlloc(size) p_psAlloc(size, __FILE__, __LINE__) … … 282 288 ); 283 289 284 #define PS_FREE (void*)1285 286 290 //@} End of Memory Management Functions 287 291 288 289 292 #ifndef DOXYGEN 290 291 void p_psCustomFree(psFreeFcn fcn,void* ptr);292 293 293 294 /*
Note:
See TracChangeset
for help on using the changeset viewer.
