Changeset 11674 for trunk/psLib/src/sys/psMemory.h
- Timestamp:
- Feb 6, 2007, 3:15:50 PM (19 years ago)
- File:
-
- 1 edited
-
trunk/psLib/src/sys/psMemory.h (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/psLib/src/sys/psMemory.h
r11672 r11674 15 15 * @ingroup MemoryManagement 16 16 * 17 * @version $Revision: 1.6 6$ $Name: not supported by cvs2svn $18 * @date $Date: 2007-02-07 0 0:36:02$17 * @version $Revision: 1.67 $ $Name: not supported by cvs2svn $ 18 * @date $Date: 2007-02-07 01:15:49 $ 19 19 * 20 20 * Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii … … 28 28 29 29 #include <stdio.h> // needed for FILE 30 #include <pthread.h> // we need a mutex to make this stuff thread safe.30 #include <pthread.h> // mutexes 31 31 #include <stdint.h> // for uint32_t 32 32 #include <stdbool.h> … … 58 58 typedef struct psMemBlock 59 59 { 60 const uint32_t startblock; ///< initialised to p_psMEMMAGIC 61 struct psMemBlock* previousBlock; ///< previous block in allocation list 62 struct psMemBlock* nextBlock; ///< next block allocation list 63 psFreeFunc freeFunc; ///< deallocator. If NULL, use generic deallocation. 64 size_t userMemorySize; ///< the size of the user-portion of the memory block 65 const psMemId id; ///< a unique ID for this allocation 66 const pthread_t tid; ///< set from pthread_self(); 67 const char *file; ///< set from __FILE__ in e.g. p_psAlloc 68 const unsigned int lineno; ///< set from __LINE__ in e.g. p_psAlloc 69 const char *func; ///< set from __func__ 60 const uint32_t startblock; ///< initialised to p_psMEMMAGIC 61 struct psMemBlock *previousBlock; ///< previous block in allocation list 62 struct psMemBlock *nextBlock; ///< next block allocation list 63 psFreeFunc freeFunc; ///< deallocator. If NULL, use generic deallocation. 64 size_t userMemorySize; ///< the size of the user-portion of the memory block 65 const psMemId id; ///< a unique ID for this allocation 66 const pthread_t tid; ///< set from pthread_self(); 67 const char *file; ///< set from __FILE__ in e.g. p_psAlloc 68 const unsigned int lineno; ///< set from __LINE__ in e.g. p_psAlloc 69 const char *func; ///< set from __func__ 70 70 71 #ifdef HAVE_BACKTRACE 71 72 72 const void **backtrace; ///< set from backtrace()73 const size_t backtraceSize; ///< set from bracktrace()73 const void **backtrace; ///< set from backtrace() 74 const size_t backtraceSize; ///< set from bracktrace() 74 75 #endif // ifdef HAVE_BACKTRACE 75 76 76 psReferenceCount refCounter; ///< how many times pointer is referenced77 bool persistent; ///< marks if this non-user persistent data like error stack, etc.78 const uint32_t endblock; ///< initialised to p_psMEMMAGIC77 psReferenceCount refCounter; ///< how many times pointer is referenced 78 bool persistent; ///< marks if this non-user persistent data like error stack, etc. 79 const uint32_t endblock; ///< initialised to p_psMEMMAGIC 79 80 } 80 81 psMemBlock; … … 85 86 */ 86 87 typedef psMemId(*psMemAllocCallback) ( 87 const psMemBlock *ptr ///< the psMemBlock just allocated88 const psMemBlock *ptr ///< the psMemBlock just allocated 88 89 ); 89 90 … … 93 94 */ 94 95 typedef psMemId(*psMemFreeCallback) ( 95 const psMemBlock *ptr ///< the psMemBlock being freed96 const psMemBlock *ptr ///< the psMemBlock being freed 96 97 ); 97 98 … … 103 104 */ 104 105 typedef void (*psMemProblemCallback) ( 105 psMemBlock* ptr, ///< the pointer to the problematic memory block. 106 const char *file, ///< the file in which the problem originated 107 unsigned int lineno ///< the line number in which the problem originated 106 const char *file, ///< File of caller 107 unsigned int lineno, ///< Line number of caller 108 const char *func, ///< Function name of caller 109 psMemBlock *ptr ///< the pointer to the problematic memory block. 108 110 ); 109 111 110 112 /** prototype of a callback function used when memory runs out 111 113 * 112 * @return void * pointer to requested buffer of the size size_t, or NULL if memory could not113 * be found.114 * @return void * pointer to requested buffer of the size size_t, or NULL if 115 * memory could not be found. 114 116 * 115 117 * @see psMemExhaustedCallbackSet 116 118 */ 117 119 typedef void *(*psMemExhaustedCallback) ( 118 size_t size ///< the size of buffer required120 size_t size ///< the size of buffer required 119 121 ); 120 122 121 /** Memory allocation. This operates much like malloc(), but is guaranteed to return a non-NULL value. 123 /** Memory allocation. This operates much like malloc(), but is guaranteed to 124 * return a non-NULL value. 122 125 * 123 126 * @return void * pointer to the allocated buffer. This will not be NULL. … … 125 128 */ 126 129 #ifdef DOXYGEN 127 128 130 void *psAlloc( 129 131 size_t size ///< Size required 130 132 ); 131 132 133 #else // #ifdef DOXYGEN 133 134 #ifdef __GNUC__135 134 void *p_psAlloc( 136 size_t size, ///< Size required137 135 const char *file, ///< File of caller 138 136 unsigned int lineno, ///< Line number of caller 139 const char *func ///< Function name of caller 137 const char *func, ///< Function name of caller 138 size_t size ///< Size required 139 #ifdef __GNUC__ 140 140 ) __attribute__((malloc)); 141 141 # else // __GNUC__ 142 void *p_psAlloc( 143 size_t size, ///< Size required 144 const char *file, ///< File of caller 145 unsigned int lineno, ///< Line number of caller 146 const char *func ///< Function name of caller 147 ); 148 #endif // __GNUC__ 149 150 /// Memory allocation. psAlloc sends file and line number to p_psAlloc. 151 #ifndef SWIG 152 #define psAlloc(size) \ 153 p_psAlloc(size, __FILE__, __LINE__, __func__) 154 #endif // ! SWIG 155 156 #endif // ! DOXYGEN 157 158 159 /** Set the deallocator routine 160 * 161 * A deallocator routine can optionally be assigned to a memory block to 162 * ensure that associated memory blocks also get freed, e.g., memory buffers 163 * referenced within a struct. 164 * 165 */ 166 #ifdef DOXYGEN 167 168 void psMemSetDeallocator( 169 void *ptr, ///< the memory block to operate on 170 psFreeFunc freeFunc ///< the function to be executed at deallocation 171 ); 172 173 #else // ifdef DOXYGEN 174 175 void p_psMemSetDeallocator( 176 void *ptr, ///< the memory block to operate on 177 psFreeFunc freeFunc, ///< the function to be executed at deallocation 178 const char *file, ///< File of caller 179 unsigned int lineno, ///< Line number of caller 180 const char *func ///< Function name of caller 181 ); 182 183 #ifndef SWIG 184 #define psMemSetDeallocator(ptr, freeFunc) \ 185 p_psMemSetDeallocator(ptr, freeFunc, __FILE__, __LINE__, __func__); 186 #endif // ! SWIG 187 188 #endif // ifdef DOXYGEN 189 190 191 /** Get the deallocator routine 192 * 193 * This function returns the deallocator for a memory block. A deallocator 194 * routine can optionally be assigned to a memory block to ensure that 195 * associated memory blocks also get freed, e.g., memory buffers referenced 196 * within a struct. 197 * 198 * @return psFreeFunc the routine to be called at deallocation. 199 */ 200 #ifdef DOXYGEN 201 202 psFreeFunc psMemGetDeallocator( 203 void *ptr ///< the memory block 204 ); 205 206 #else // ifdef DOXYGEN 207 208 psFreeFunc p_psMemGetDeallocator( 209 void *ptr, ///< the memory block 210 const char *file, ///< File of caller 211 unsigned int lineno, ///< Line number of caller 212 const char *func ///< Function name of caller 213 ); 214 215 #ifndef SWIG 216 #define psMemGetDeallocator(ptr) \ 217 p_psMemGetDeallocator(ptr, __FILE__, __LINE__, __func__) 218 #endif // ! SWIG 219 220 #endif // ifdef DOXYGEN 221 222 223 /** Activate or Deactivate thread safety and mutex locking in the memory management. 224 * 225 * psMemThreadSafety shall turn on thread safety in the memory management functions if 226 * safe is true, and deactivate all mutex locking in the memory management functions if 227 * safe is false. The function shall return the previous value of the thread safety. 228 * Note that the default behaviour of the library shall be for the locking to be performed. 229 * 230 * @return bool: The previous value of the thread safety. 231 */ 232 bool psMemSetThreadSafety( 233 bool safe ///< boolean for turning on/off thread safety 234 ); 235 236 /** Get the current state of thread safety and mutex locking in the memory management. 237 * 238 * psMemGetThreadSafety shall return the current state of thread safety in the memory management system. 239 * 240 * @return bool: The current state of thread safety. 241 */ 242 bool psMemGetThreadSafety(void); 243 244 245 /** Set the memory as persistent so that it is ignored when detecting memory leaks. 246 * 247 * Used to mark a memory block as persistent data within the library, 248 * i.e., non user-level data used to hold psLib's state or cache data. Such 249 * examples of this class of memory is psTrace's trace-levels and dynamic 250 * error codes. 251 * 252 * Memory marked as persistent is excluded from memory leak checks. 253 * 254 */ 255 #ifdef DOXYGEN 256 257 void psMemSetPersistent( 258 void *ptr, ///< the memory block to operate on 259 bool value, ///< true if memory is persistent, otherwise false 260 ); 261 262 #else // #ifdef DOXYGEN 263 264 void p_psMemSetPersistent( 265 void *ptr, ///< the memory block to operate on 266 bool value, ///< true if memory is persistent, otherwise false 267 const char *file, ///< File of caller 268 unsigned int lineno, ///< Line number of caller 269 const char *func ///< Function name of caller 270 ); 271 272 #ifndef SWIG 273 #define psMemSetPersistent(ptr, value) \ 274 p_psMemSetPersistent(ptr, value, __FILE__, __LINE__, __func__); 275 #endif // ! SWIG 276 277 #endif // DOXYGEN 278 279 280 /** Set whether allocated memory is persistent 281 * 282 * Set whether allocated memory is persistent. The defeault is false. 283 * 284 * @return bool: The previous value of whether all allocated memory is persistent 285 */ 286 bool p_psMemAllocatePersistent(bool is_persistent); ///< Should all memory allocated be persistent? 287 288 289 /** Get the memory's persistent flag. 290 * 291 * Checks if a memory block has been marked as persistent by 292 * p_psMemSetPresistent. 293 * 294 * Memory marked as persistent is excluded from memory leak checks. 295 * 296 * @return bool true if memory is marked persistent, otherwise false. 297 */ 298 #ifdef DOXYGEN 299 300 bool psMemGetPersistent( 301 void *ptr, ///< the memory block to check. 302 ); 303 #else // ifdef DOXYGEN 304 305 bool p_psMemGetPersistent( 306 void *ptr, ///< the memory block to check. 307 const char *file, ///< File of caller 308 unsigned int lineno, ///< Line number of caller 309 const char *func ///< Function name of caller 310 ); 311 312 #ifndef SWIG 313 #define psMemGetPersistent(ptr) \ 314 p_MemGetPersistent(ptr, __FILE__, __LINE__, __func__); 315 #endif // ! SWIG 316 317 #endif // DOXYGEN 318 319 320 /** Memory re-allocation. This operates much like realloc(), but is guaranteed to return a non-NULL value. 321 * 322 * @return void * pointer to resized buffer. This will not be NULL. 323 * @see psAlloc, psFree 324 */ 325 #ifdef DOXYGEN 326 327 void *psRealloc( 328 void *ptr, ///< Pointer to re-allocate 329 size_t size ///< Size required 330 ); 331 #else // #ifdef DOXYGEN 332 #ifdef __GNUC__ 333 void *p_psRealloc( 334 void *ptr, ///< Pointer to re-allocate 335 size_t size, ///< Size required 336 const char *file, ///< File of caller 337 unsigned int lineno, ///< Line number of caller 338 const char *func ///< Function name of caller 339 ) __attribute__((malloc)); 340 # else // __GNUC__ 341 void *p_psRealloc( 342 void *ptr, ///< Pointer to re-allocate 343 size_t size, ///< Size required 142 ); 143 #endif // __GNUC__ 144 145 /// Memory allocation. psAlloc sends file and line number to p_psAlloc. 146 #ifndef SWIG 147 #define psAlloc(size) \ 148 p_psAlloc(__FILE__, __LINE__, __func__, size) 149 #endif // ! SWIG 150 #endif // ! DOXYGEN 151 152 153 /** Set the deallocator routine 154 * 155 * A deallocator routine can optionally be assigned to a memory block to 156 * ensure that associated memory blocks also get freed, e.g., memory buffers 157 * referenced within a struct. 158 * 159 */ 160 #ifdef DOXYGEN 161 void psMemSetDeallocator( 162 void *ptr, ///< the memory block to operate on 163 psFreeFunc freeFunc ///< the function to be executed at deallocation 164 ); 165 #else // ifdef DOXYGEN 166 void p_psMemSetDeallocator( 344 167 const char *file, ///< File of caller 345 168 unsigned int lineno, ///< Line number of caller 346 const char *func ///< Function name of caller 347 ); 348 #endif // __GNUC__ 349 350 /// Memory re-allocation. psRealloc sends file and line number to p_psRealloc. 351 #ifndef SWIG 352 #define psRealloc(ptr, size) \ 353 p_psRealloc(ptr, size, __FILE__, __LINE__, __func__) 354 #endif // ! SWIG 355 356 #endif // ! DOXYGEN 357 358 359 /** Free memory. This operates much like free(). 360 * 361 * @see psAlloc, psRealloc 362 */ 363 #ifdef DOXYGEN 364 void psFree( 365 void *ptr ///< Pointer to free, if NULL, function returns immediately. 366 ); 367 #else // #ifdef DOXYGEN 368 369 /// Free memory. psFree sends file and line number to p_psFree. 370 #ifndef SWIG 371 #define psFree(ptr) \ 372 p_psMemDecrRefCounter((void **)ptr, __FILE__, __LINE__, __func__); 373 #endif // ! SWIG 374 375 #endif // ! DOXYGEN 376 377 378 /** Check for memory leaks. This scans for allocated memory buffers not freed with an ID not less than id0. 379 * This is used to check for memory leaks by: 380 * -# before a block of code to be checked, store the current ID count via psGetMemId 381 * -# after the block of code to be checked, call this function using the ID stored above. If all 382 * memory in the block that was allocated has been freed, this call should output nothing and 383 * return 0. 384 * 385 * If memory leaks are found, the Memory Problem callback will be called as well. 386 * 387 * @return int number of memory blocks found as 'leaks', i.e., the number of currently allocated memory 388 * blocks above id0 that have not been freed. 389 * @see psAlloc, psFree, psgetMemId, psMemProblemCallbackSet 390 */ 391 #ifdef DOXYGEN 392 int psMemCheckLeaks( 393 psMemId id0, ///< don't list blocks with id < id0 394 psMemBlock ***array, ///< pointer to array of pointers to leaked blocks, or NULL 395 FILE * fd, ///< print list of leaks to fd (or NULL) 396 bool persistence ///< make check across all object even persistent ones 397 ); 398 #else // ifdef DOXYGEN 399 int p_psMemCheckLeaks( 400 psMemId id0, ///< don't list blocks with id < id0 401 psMemBlock ***array, ///< pointer to array of pointers to leaked blocks, or NULL 402 FILE * fd, ///< print list of leaks to fd (or NULL) 403 bool persistence, ///< make check across all object even persistent ones 404 const char *file, ///< File of caller 405 unsigned int lineno, ///< Line number of caller 406 const char *func ///< Function name of caller 407 ); 408 #ifndef SWIG 409 #define psMemCheckLeaks(id0, array, fd, persistence) \ 410 p_psMemCheckLeaks(id0, array, fd, persistence, __FILE__, __LINE__, __func__) 411 #endif // ifndef SWIG 412 #endif // ifdef DOXYGEN 413 414 415 /** Check for memory corruption. Scans all currently allocated memory buffers and checks for corruptions, 416 * i.e., invalid markers that signify a buffer under/overflow. 417 * 418 * @return int 419 * 420 */ 421 #ifdef DOXYGEN 422 int psMemCheckCorruption( 423 FILE *output, ///< FILE to write corrupted blocks too 424 bool abort_on_error ///< Abort on detecting corruption? 425 ); 426 #else // ifdef DOXYGEN 427 int p_psMemCheckCorruption( 428 FILE *output, ///< FILE to write corrupted blocks too 429 bool abort_on_error, ///< Abort on detecting corruption? 430 const char *file, ///< File of caller 431 unsigned int lineno, ///< Line number of caller 432 const char *func ///< Function name of caller 433 ); 434 #ifndef SWIG 435 #define psMemCheckCorruption(output, abort_on_error) \ 436 p_psMemCheckCorruption(output, abort_on_error, __FILE__, __LINE__, __func__) 437 #endif // ifndef SWIG 438 #endif // ifdef DOXYGEN 439 440 441 /** Return reference counter 442 * 443 * @return psReferenceCount 444 * 445 */ 446 #ifdef DOXYGEN 447 448 psReferenceCount psMemGetRefCounter( 449 void *ptr ///< Pointer to get refCounter for 450 ); 451 452 #else // ifdef DOXYGEN 453 454 psReferenceCount p_psMemGetRefCounter( 455 void *ptr, ///< Pointer to get refCounter for 456 const char *file, ///< File of call 457 unsigned int lineno, ///< Line number of call 458 const char *func ///< Function name of caller 459 ); 460 461 #ifndef SWIG 462 #define psMemGetRefCounter(ptr) \ 463 p_psMemGetRefCounter(ptr, __FILE__, __LINE__, __func__) 464 #endif // !SWIG 465 466 #endif // !DOXYGEN 467 468 469 /** Increment reference counter and return the pointer 470 * 471 * @return void * 472 * 473 */ 474 #ifdef DOXYGEN 475 476 void *psMemIncrRefCounter( 477 void *ptr ///< Pointer to increment refCounter, and return 478 ); 479 #else // ifdef DOXYGEN 480 481 void *p_psMemIncrRefCounter( 482 void *ptr, ///< Pointer to increment refCounter, and return 483 const char *file, ///< File of call 484 unsigned int lineno, ///< Line number of call 485 const char *func ///< Function name of caller 486 ); 487 488 #ifndef SWIG 489 #define psMemIncrRefCounter(ptr) \ 490 p_psMemIncrRefCounter(ptr, __FILE__, __LINE__, __func__) 491 #endif // !SWIG 492 493 #endif // !DOXYGEN 494 495 496 /** Decrement reference counter and return the pointer 497 * 498 * 499 * @return void * the pointer deremented in refCount, or NULL if pointer is 500 * fully dereferenced. 501 */ 502 #ifdef DOXYGEN 503 504 void *psMemDecrRefCounter( 505 void *ptr ///< Pointer to decrement refCounter, and return 506 ); 507 508 #else // DOXYGEN 509 510 void *p_psMemDecrRefCounter( 511 void *ptr, ///< Pointer to decrement refCounter, and return 512 const char *file, ///< File of call 513 unsigned int lineno, ///< Line number of call 514 const char *func ///< Function name of caller 515 ); 516 517 #ifndef SWIG 518 #define psMemDecrRefCounter(ptr) \ 519 p_psMemDecrRefCounter(ptr, __FILE__, __LINE__, __func__) 520 #endif // !SWIG 521 522 #endif // !DOXYGEN 523 524 #if 0 // psMemSetRefCounter 525 /** Set reference counter and return the pointer 526 * 527 * @return void * the pointer with refCount set, or NULL if pointer is 528 * fully dereferenced. 529 */ 530 #ifdef DOXYGEN 531 void * psMemSetRefCounter( 532 void * ptr, ///< Pointer to decrement refCounter, and return 533 psReferenceCount count ///< New reference count 534 ); 535 #else // DOXYGEN 536 void * p_psMemSetRefCounter( 537 void * vptr, ///< Pointer to decrement refCounter, and return 538 psReferenceCount count, ///< New reference count 539 const char *file, ///< File of call 540 psS32 lineno ///< Line number of call 541 ); 542 543 #ifndef SWIG 544 #define psMemSetRefCounter(vptr, count) p_psMemSetRefCounter(vptr, count, __FILE__, __LINE__) 545 #endif // !SWIG 546 547 #endif // !DOXYGEN 548 #endif // psMemSetRefCounter 549 550 /** Set callback for out-of-memory. 551 * 552 * If not enough memory is available to satisfy a request by psAlloc or 553 * psRealloc, these functions attempt to find an alternative solution by 554 * calling the psMemExhaustedCallback, a function which may be set by the 555 * programmer in appropriate circumstances, rather than immediately fail. 556 * The typical use of such a feature may be when a program needs a large 557 * chunk of memory to do an operation, but the exact size is not critical. 558 * This feature gives the programmer the opportunity to make a smaller 559 * request and try again, limiting the size of the operating buffer. 560 * 561 * @return psMemExhaustedCallback old psMemExhaustedCallback function 562 */ 563 psMemExhaustedCallback psMemExhaustedCallbackSet( 564 psMemExhaustedCallback func ///< Function to run at memory exhaustion 565 ); 566 567 /** Set call back for when a particular memory block is allocated 568 * 569 * A private variable, p_psMemAllocID, can be used to trace the allocation 570 * and freeing of specific memory blocks. If p_psMemAllocID is set and a 571 * memory block with that ID is allocated, psMemAllocCallback is called 572 * just before memory is returned to the calling function. 573 * 574 * @return psMemAllocCallback old psMemAllocCallback function 575 */ 576 psMemAllocCallback psMemAllocCallbackSet( 577 psMemAllocCallback func ///< Function to run at memory allocation of specific mem block 578 ); 579 580 /** Set call back for when a particular memory block is freed 581 * 582 * A private variable, p_psMemFreeID, can be used to trace the freeing of 583 * specific memory blocks. If p_psMemFreeID is set and the memory block with 584 * the ID is about to be freed, the psMemFreeCallback callback is called just 585 * before the memory block is freed. 586 * 587 * @return psMemFreeCallback old psMemFreeCallback function 588 */ 589 psMemFreeCallback psMemFreeCallbackSet( 590 psMemFreeCallback func ///< Function to run at memory free of specific mem block 591 ); 592 593 /** get next memory ID 594 * 595 * @return psMemId the next memory ID to be used 596 */ 597 psMemId psMemGetId(void); 598 599 /** get the last memory ID used 600 * 601 * @return psMemId the last memory ID used 602 */ 603 psMemId psMemGetLastId(void); 604 605 /** set p_psMemAllocID to specific id 606 * 607 * A private variable, p_psMemAllocID, can be used to trace the allocation 608 * and freeing of specific memory blocks. If p_psMemAllocID is set and a 609 * memory block with that ID is allocated, psMemAllocCallback is called 610 * just before memory is returned to the calling function. 611 * 612 * @return psMemId 613 * 614 * @see psMemAllocCallbackSet 615 */ 616 psMemId psMemAllocCallbackSetID( 617 psMemId id ///< ID to set 618 ); 619 620 /** set p_psMemFreeID to id 621 * 622 * A private variable, p_psMemFreeID, can be used to trace the freeing of 623 * specific memory blocks. If p_psMemFreeID is set and the memory block with 624 * the ID is about to be freed, the psMemFreeCallback callback is called just 625 * before the memory block is freed. 626 * 627 * @return psMemId the old p_psMemFreeID 628 * 629 * @see psMemFreeCallbackSet 630 */ 631 psMemId psMemFreeCallbackSetID( 632 psMemId id ///< ID to set 633 ); 634 635 636 /** return statistics on memory usage 637 * 638 * @return the total amount of memory owned by psLib; if non-NULL also provide 639 * a breakdown into allocated and allocated-and-persistent 640 */ 641 size_t psMemStats(const bool print, ///< print details as they're found? 642 size_t *allocated, ///< memory that's currently allocated (but not persistent) 643 size_t *persistent); ///< persistent memory that's currently allocated 644 645 /** print detailed information about a psMemBlock 646 * 647 * This function prints a detailed description of a psMemBlock to output. 648 * 649 * @return the return status of fprintf() 650 */ 651 int psMemBlockPrint( 652 FILE *output, ///< FILE to write information too 653 const psMemBlock *memBlock ///< psMemBlock to be examined 654 ); 655 656 657 /// @} end of SysUtils 658 659 #ifndef DOXYGEN 660 661 /* 662 * Ensure that any program using malloc/realloc/free will fail to compile 663 */ 664 #ifndef PS_ALLOW_MALLOC 665 #ifdef __GNUC__ 666 #pragma GCC poison malloc realloc calloc free 667 #else // __GNUC__ 668 #define malloc(S) _Pragma("error Use of malloc is not allowed. Use psAlloc instead.") 669 #define realloc(P,S) _Pragma("error Use of realloc is not allowed. Use psRealloc instead.") 670 #define calloc(S) _Pragma("error Use of calloc is not allowed. Use psAlloc instead.") 671 #define free(P) _Pragma("error Use of free is not allowed. Use psFree instead.") 672 #endif // ! __GNUC__ 673 #endif // #ifndef PS_ALLOW_MALLOC 674 675 #endif // #ifndef DOXYGEN 676 #endif // #ifndef PS_MEMORY_H 169 const char *func, ///< Function name of caller 170 void *ptr, ///< the memory block to operate on 171 psFreeFunc freeFunc ///< the function to be executed at deallocation 172 ); 173 #ifndef SWIG 174 #define psMemSetDeallocator(ptr, freeFunc) \ 175 p_psMemSetDeallocator(__FILE__, __LINE__, __func__, ptr, freeFunc) 176 #endif // ! SWIG 177 #endif // ifdef DOXYGEN 178 179 180 /** Get the deallocator routine 181 * 182 * This function returns the deallocator for a memory block. A deallocator 183 * routine can optionally be assigned to a memory block to ensure that 184 * associated memory blocks also get freed, e.g., memory buffers referenced 185 * within a struct. 186 * 187 * @return psFreeFunc the routine to be called at deallocation. 188 */ 189 #ifdef DOXYGEN 190 psFreeFunc psMemGetDeallocator( 191 void *ptr ///< the memory block 192 ); 193 #else // ifdef DOXYGEN 194 psFreeFunc p_psMemGetDeallocator( 195 const char *file, ///< File of caller 196 unsigned int lineno, ///< Line number of caller 197 const char *func, ///< Function name of caller 198 void *ptr ///< the memory block 199 ); 200 #ifndef SWIG 201 #define psMemGetDeallocator(ptr) \ 202 p_psMemGetDeallocator(__FILE__, __LINE__, __func__, ptr) 203 #endif // ! SWIG 204 #endif // ifdef DOXYGEN 205 206 207 /** Activate or Deactivate thread safety and mutex locking in the memory 208 * management. 209 * 210 * psMemThreadSafety shall turn on thread safety in the memory management 211 * functions if safe is true, and deactivate all mutex locking in the memory 212 * management functions if safe is false. The function shall return the 213 * previous value of the thread safety. Note that the default behaviour of 214 * the library shall be for the locking to be performed. 215 * 216 * @return bool: The previous value of the thread safety. 217 */ 218 bool psMemSetThreadSafety( 219 bool safe ///< boolean for turning on/off thread safety 220 ); 221 222 /** Get the current state of thread safety and mutex locking in the memory 223 * management. 224 * 225 * psMemGetThreadSafety shall return the current state of thread safety in the 226 * memory management system. 227 * 228 * @return bool: The current state of thread safety. 229 */ 230 bool psMemGetThreadSafety(void); 231 232 233 /** Set the memory as persistent so that it is ignored when detecting memory 234 * leaks. 235 * 236 * Used to mark a memory block as persistent data within the library, 237 * i.e., non user-level data used to hold psLib's state or cache data. Such 238 * examples of this class of memory is psTrace's trace-levels and dynamic 239 * error codes. 240 * 241 * Memory marked as persistent is excluded from memory leak checks. 242 * 243 */ 244 #ifdef DOXYGEN 245 void psMemSetPersistent( 246 void *ptr, ///< the memory block to operate on 247 bool value, ///< true if memory is persistent, otherwise false 248 ); 249 #else // #ifdef DOXYGEN 250 void p_psMemSetPersistent( 251 const char *file, ///< File of caller 252 unsigned int lineno, ///< Line number of caller 253 const char *func, ///< Function name of caller 254 void *ptr, ///< the memory block to operate on 255 bool value ///< true if memory is persistent, otherwise false 256 ); 257 #ifndef SWIG 258 #define psMemSetPersistent(ptr, value) \ 259 p_psMemSetPersistent(__FILE__, __LINE__, __func__, ptr, value) 260 #endif // ! SWIG 261 #endif // DOXYGEN 262 263 264 /** Set whether allocated memory is persistent 265 * 266 * Set whether allocated memory is persistent. The defeault is false. 267 * 268 * @return bool: The previous value of whether all allocated memory is 269 * persistent 270 */ 271 bool p_psMemAllocatePersistent(bool is_persistent); ///< Should all memory allocated be persistent? 272 273 274 /** Get the memory's persistent flag. 275 * 276 * Checks if a memory block has been marked as persistent by 277 * p_psMemSetPresistent. 278 * 279 * Memory marked as persistent is excluded from memory leak checks. 280 * 281 * @return bool true if memory is marked persistent, otherwise false. 282 */ 283 #ifdef DOXYGEN 284 bool psMemGetPersistent( 285 void *ptr, ///< the memory block to check. 286 ); 287 #else // ifdef DOXYGEN 288 bool p_psMemGetPersistent( 289 const char *file, ///< File of caller 290 unsigned int lineno, ///< Line number of caller 291 const char *func, ///< Function name of caller 292 void *ptr ///< the memory block to check. 293 ); 294 #ifndef SWIG 295 #define psMemGetPersistent(ptr) \ 296 p_psMemGetPersistent(__FILE__, __LINE__, __func__, ptr) 297 #endif // ! SWIG 298 #endif // DOXYGEN 299 300 301 /** Memory re-allocation. This operates much like realloc(), but is guaranteed 302 * to return a non-NULL value. 303 * 304 * @return void * pointer to resized buffer. This will not be NULL. 305 * @see psAlloc, psFree 306 */ 307 #ifdef DOXYGEN 308 void *psRealloc( 309 void *ptr, ///< Pointer to re-allocate 310 size_t size ///< Size required 311 ); 312 #else // #ifdef DOXYGEN 313 void *p_psRealloc( 314 const char *file, ///< File of caller 315 unsigned int lineno, ///< Line number of caller 316 const char *func, ///< Function name of caller 317 void *ptr, ///< Pointer to re-allocate 318 size_t size ///< Size required 319 #ifdef __GNUC__ 320 ) __attribute__((malloc)); 321 # else // __GNUC__ 322 ); 323 #endif // __GNUC__ 324 #ifndef SWIG 325 #define psRealloc(ptr, size) \ 326 p_psRealloc(__FILE__, __LINE__, __func__, ptr, size) 327 #endif // ! SWIG 328 #endif // ! DOXYGEN 329 330 331 /** Free memory. This operates much like free(). 332 * 333 * @see psAlloc, psRealloc 334 */ 335 #ifdef DOXYGEN 336 void psFree( 337 void *ptr ///< Pointer to free, if NULL, function returns immediately. 338 ); 339 #else // #ifdef DOXYGEN 340 /// Free memory. psFree sends file and line number to p_psFree. 341 #ifndef SWIG 342 #define psFree(ptr) \ 343 psMemDecrRefCounter(ptr) 344 #endif // ! SWIG 345 #endif // ! DOXYGEN 346 347 348 /** Check for memory leaks. This scans for allocated memory buffers not freed 349 * with an ID not less than id0. This is used to check for memory leaks by: -# 350 * before a block of code to be checked, store the current ID count via 351 * psGetMemId -# after the block of code to be checked, call this function 352 * using the ID stored above. If all memory in the block that was allocated 353 * has been freed, this call should output nothing and return 0. 354 * 355 * If memory leaks are found, the Memory Problem callback will be called as 356 * well. 357 * 358 * @return int number of memory blocks found as 'leaks', i.e., the number of 359 * currently allocated memory blocks above id0 that have not been freed. @see 360 * psAlloc, psFree, psgetMemId, psMemProblemCallbackSet 361 */ 362 #ifdef DOXYGEN 363 int psMemCheckLeaks( 364 psMemId id0, ///< don't list blocks with id < id0 365 psMemBlock ***array, ///< pointer to array of pointers to leaked blocks, or NULL 366 FILE * fd, ///< print list of leaks to fd (or NULL) 367 bool persistence ///< make check across all object even persistent ones 368 ); 369 #else // ifdef DOXYGEN 370 int p_psMemCheckLeaks( 371 const char *file, ///< File of caller 372 unsigned int lineno, ///< Line number of caller 373 const char *func, ///< Function name of caller 374 psMemId id0, ///< don't list blocks with id < id0 375 psMemBlock ***array, ///< pointer to array of pointers to leaked blocks, or NULL 376 FILE * fd, ///< print list of leaks to fd (or NULL) 377 bool persistence ///< make check across all object even persistent ones 378 ); 379 #ifndef SWIG 380 #define psMemCheckLeaks(id0, array, fd, persistence) \ 381 p_psMemCheckLeaks(__FILE__, __LINE__, __func__, id0, array, fd, persistence) 382 #endif // ifndef SWIG 383 #endif // ifdef DOXYGEN 384 385 386 /** Check for memory corruption. Scans all currently allocated memory buffers 387 * and checks for corruptions, i.e., invalid markers that signify a buffer 388 * under/overflow. 389 * 390 * @return int 391 * 392 */ 393 #ifdef DOXYGEN 394 int psMemCheckCorruption( 395 FILE *output, ///< FILE to write corrupted blocks too 396 bool abort_on_error ///< Abort on detecting corruption? 397 ); 398 #else // ifdef DOXYGEN 399 int p_psMemCheckCorruption( 400 const char *file, ///< File of caller 401 unsigned int lineno, ///< Line number of caller 402 const char *func, ///< Function name of caller 403 FILE *output, ///< FILE to write corrupted blocks too 404 bool abort_on_error ///< Abort on detecting corruption? 405 ); 406 #ifndef SWIG 407 #define psMemCheckCorruption(output, abort_on_error) \ 408 p_psMemCheckCorruption(__FILE__, __LINE__, __func__, output, abort_on_error) 409 #endif // ifndef SWIG 410 #endif // ifdef DOXYGEN 411 412 413 /** Return reference counter 414 * 415 * @return psReferenceCount 416 * 417 */ 418 #ifdef DOXYGEN 419 psReferenceCount psMemGetRefCounter( 420 void *ptr ///< Pointer to get refCounter for 421 ); 422 423 #else // ifdef DOXYGEN 424 psReferenceCount p_psMemGetRefCounter( 425 const char *file, ///< File of call 426 unsigned int lineno, ///< Line number of call 427 const char *func, ///< Function name of caller 428 void *ptr ///< Pointer to get refCounter for 429 ); 430 #ifndef SWIG 431 #define psMemGetRefCounter(ptr) \ 432 p_psMemGetRefCounter(__FILE__, __LINE__, __func__, ptr) 433 #endif // !SWIG 434 #endif // !DOXYGEN 435 436 437 /** Increment reference counter and return the pointer 438 * 439 * @return void * 440 * 441 */ 442 #ifdef DOXYGEN 443 void *psMemIncrRefCounter( 444 void *ptr ///< Pointer to increment refCounter, and return 445 ); 446 #else // ifdef DOXYGEN 447 void *p_psMemIncrRefCounter( 448 const char *file, ///< File of call 449 unsigned int lineno, ///< Line number of call 450 const char *func, ///< Function name of caller 451 void *ptr ///< Pointer to increment refCounter, and return 452 ); 453 #ifndef SWIG 454 #define psMemIncrRefCounter(ptr) \ 455 p_psMemIncrRefCounter(__FILE__, __LINE__, __func__, ptr) 456 #endif // !SWIG 457 #endif // !DOXYGEN 458 459 460 /** Decrement reference counter and return the pointer 461 * 462 * 463 * @return void * the pointer deremented in refCount, or NULL if pointer is 464 * fully dereferenced. 465 */ 466 #ifdef DOXYGEN 467 void *psMemDecrRefCounter( 468 void *ptr ///< Pointer to decrement refCounter, and return 469 ); 470 #else // DOXYGEN 471 void *p_psMemDecrRefCounter( 472 const char *file, ///< File of call 473 unsigned int lineno, ///< Line number of call 474 const char *func, ///< Function name of caller 475 void *ptr ///< Pointer to decrement refCounter, and return 476 ); 477 #ifndef SWIG 478 #define psMemDecrRefCounter(ptr) \ 479 p_psMemDecrRefCounter(__FILE__, __LINE__, __func__, ptr) 480 #endif // !SWIG 481 #endif // !DOXYGEN 482 483 484 #if 0 // psMemSetRefCounter 485 /** Set reference counter and return the pointer 486 * 487 * @return void * the pointer with refCount set, or NULL if pointer is 488 * fully dereferenced. 489 */ 490 #ifdef DOXYGEN 491 void * psMemSetRefCounter( 492 void * ptr, ///< Pointer to decrement refCounter, and return 493 psReferenceCount count ///< New reference count 494 ); 495 #else // DOXYGEN 496 void * p_psMemSetRefCounter( 497 void * vptr, ///< Pointer to decrement refCounter, and return 498 psReferenceCount count, ///< New reference count 499 const char *file, ///< File of call 500 psS32 lineno ///< Line number of call 501 ); 502 503 #ifndef SWIG 504 #define psMemSetRefCounter(vptr, count) p_psMemSetRefCounter(vptr, count, __FILE__, __LINE__) 505 #endif // !SWIG 506 507 #endif // !DOXYGEN 508 #endif // psMemSetRefCounter 509 510 /** Set callback for out-of-memory. 511 * 512 * If not enough memory is available to satisfy a request by psAlloc or 513 * psRealloc, these functions attempt to find an alternative solution by 514 * calling the psMemExhaustedCallback, a function which may be set by the 515 * programmer in appropriate circumstances, rather than immediately fail. 516 * The typical use of such a feature may be when a program needs a large 517 * chunk of memory to do an operation, but the exact size is not critical. 518 * This feature gives the programmer the opportunity to make a smaller 519 * request and try again, limiting the size of the operating buffer. 520 * 521 * @return psMemExhaustedCallback old psMemExhaustedCallback function 522 */ 523 psMemExhaustedCallback psMemExhaustedCallbackSet( 524 psMemExhaustedCallback func ///< Function to run at memory exhaustion 525 ); 526 527 528 /** Set call back for when a particular memory block is allocated 529 * 530 * A private variable, p_psMemAllocID, can be used to trace the allocation 531 * and freeing of specific memory blocks. If p_psMemAllocID is set and a 532 * memory block with that ID is allocated, psMemAllocCallback is called 533 * just before memory is returned to the calling function. 534 * 535 * @return psMemAllocCallback old psMemAllocCallback function 536 */ 537 psMemAllocCallback psMemAllocCallbackSet( 538 psMemAllocCallback func ///< Function to run at memory allocation of specific mem block 539 ); 540 541 542 /** Set call back for when a particular memory block is freed 543 * 544 * A private variable, p_psMemFreeID, can be used to trace the freeing of 545 * specific memory blocks. If p_psMemFreeID is set and the memory block with 546 * the ID is about to be freed, the psMemFreeCallback callback is called just 547 * before the memory block is freed. 548 * 549 * @return psMemFreeCallback old psMemFreeCallback function 550 */ 551 psMemFreeCallback psMemFreeCallbackSet( 552 psMemFreeCallback func ///< Function to run at memory free of specific mem block 553 ); 554 555 556 /** get next memory ID 557 * 558 * @return psMemId the next memory ID to be used 559 */ 560 psMemId psMemGetId(void); 561 562 563 /** get the last memory ID used 564 * 565 * @return psMemId the last memory ID used 566 */ 567 psMemId psMemGetLastId(void); 568 569 570 /** set p_psMemAllocID to specific id 571 * 572 * A private variable, p_psMemAllocID, can be used to trace the allocation 573 * and freeing of specific memory blocks. If p_psMemAllocID is set and a 574 * memory block with that ID is allocated, psMemAllocCallback is called 575 * just before memory is returned to the calling function. 576 * 577 * @return psMemId 578 * 579 * @see psMemAllocCallbackSet 580 */ 581 psMemId psMemAllocCallbackSetID( 582 psMemId id ///< ID to set 583 ); 584 585 586 /** set p_psMemFreeID to id 587 * 588 * A private variable, p_psMemFreeID, can be used to trace the freeing of 589 * specific memory blocks. If p_psMemFreeID is set and the memory block with 590 * the ID is about to be freed, the psMemFreeCallback callback is called just 591 * before the memory block is freed. 592 * 593 * @return psMemId the old p_psMemFreeID 594 * 595 * @see psMemFreeCallbackSet 596 */ 597 psMemId psMemFreeCallbackSetID( 598 psMemId id ///< ID to set 599 ); 600 601 602 /** return statistics on memory usage 603 * 604 * @return the total amount of memory owned by psLib; if non-NULL also provide 605 * a breakdown into allocated and allocated-and-persistent 606 */ 607 size_t psMemStats(const bool print, ///< print details as they're found? 608 size_t *allocated, ///< memory that's currently allocated (but not persistent) 609 size_t *persistent); ///< persistent memory that's currently allocated 610 611 /** print detailed information about a psMemBlock 612 * 613 * This function prints a detailed description of a psMemBlock to output. 614 * 615 * @return the return status of fprintf() 616 */ 617 int psMemBlockPrint( 618 FILE *output, ///< FILE to write information too 619 const psMemBlock *memBlock ///< psMemBlock to be examined 620 ); 621 622 623 /// @} end of SysUtils 624 625 #ifndef DOXYGEN 626 627 /* 628 * Ensure that any program using malloc/realloc/free will fail to compile 629 */ 630 #ifndef PS_ALLOW_MALLOC 631 #ifdef __GNUC__ 632 #pragma GCC poison malloc realloc calloc free 633 #else // __GNUC__ 634 #define malloc(S) _Pragma("error Use of malloc is not allowed. Use psAlloc instead.") 635 #define realloc(P,S) _Pragma("error Use of realloc is not allowed. Use psRealloc instead.") 636 #define calloc(S) _Pragma("error Use of calloc is not allowed. Use psAlloc instead.") 637 #define free(P) _Pragma("error Use of free is not allowed. Use psFree instead.") 638 #endif // ! __GNUC__ 639 #endif // #ifndef PS_ALLOW_MALLOC 640 641 #endif // #ifndef DOXYGEN 642 #endif // #ifndef PS_MEMORY_H
Note:
See TracChangeset
for help on using the changeset viewer.
