| 1462 | |
| 1463 | #if !defined(TORQUE_DISABLE_MEMORY_MANAGER) |
| 1464 | static void* realloc(void* mem, dsize_t size, const char* fileName, const U32 line) |
| 1465 | { |
| 1466 | //validate(); |
| 1467 | if (!size) { |
| 1468 | free(mem, false); |
| 1469 | return NULL; |
| 1470 | } |
| 1471 | if(!mem) |
| 1472 | return alloc(size, false, fileName, line); |
| 1473 | |
| 1474 | #ifdef TORQUE_MULTITHREAD |
| 1475 | if(!gMemMutex) |
| 1476 | gMemMutex = Mutex::createMutex(); |
| 1477 | |
| 1478 | Mutex::lockMutex(gMemMutex); |
| 1479 | #endif |
| 1480 | |
| 1481 | AllocatedHeader* hdr = ((AllocatedHeader *)mem) - 1; |
| 1482 | #ifdef TORQUE_DEBUG_GUARD |
| 1483 | checkGuard( ( Header* ) hdr, true ); |
| 1484 | #endif |
| 1485 | |
| 1486 | AssertFatal((hdr->flags & Allocated) == Allocated, "Bad block flags."); |
| 1487 | |
| 1488 | size = (size + 0xF) & ~0xF; |
| 1489 | |
| 1490 | U32 oldSize = hdr->size; |
| 1491 | if(oldSize == size) |
| 1492 | { |
| 1493 | #ifdef TORQUE_MULTITHREAD |
| 1494 | Mutex::unlockMutex(gMemMutex); |
| 1495 | #endif |
| 1496 | return mem; |
| 1497 | } |
| 1498 | PROFILE_START(MemoryRealloc); |
| 1499 | |
| 1500 | FreeHeader *next = (FreeHeader *) hdr->next; |
| 1501 | |
| 1502 | #ifdef TORQUE_DEBUG_GUARD |
| 1503 | // adjust header size and allocated bytes size |
| 1504 | hdr->realSize += size - oldSize; |
| 1505 | gBytesAllocated += size - oldSize; |
| 1506 | if (gEnableLogging) |
| 1507 | logRealloc(hdr, size); |
| 1508 | |
| 1509 | // Add reallocated flag, note header changes will not persist if the realloc |
| 1510 | // decides tofree, and then perform a fresh allocation for the memory. The flag will |
| 1511 | // be manually set again after this takes place, down at the bottom of this fxn. |
| 1512 | hdr->flags |= Reallocated; |
| 1513 | |
| 1514 | // Note on Above ^ |
| 1515 | // A more useful/robust implementation can be accomplished by storing an additional |
| 1516 | // AllocatedHeader* in DEBUG_GUARD builds inside the AllocatedHeader structure |
| 1517 | // itself to create a sort of reallocation history. This will be, essentially, |
| 1518 | // a allocation header stack for each allocation. Each time the memory is reallocated |
| 1519 | // it should use dRealMalloc (IMPORTANT!!) to allocate a AllocatedHeader* and chain |
| 1520 | // it to the reallocation history chain, and the dump output changed to display |
| 1521 | // reallocation history. It is also important to clean up this chain during 'free' |