AllocatorRealloc
Description
Convenience cascade: tries AllocatorResize first, falls back to AllocatorRemap. Both sub-calls are _Generic-dispatched, so for a typed pointer the whole cascade resolves to two typed-direct function calls – no indirect dispatch and no outer wrapper frame. Allocator * routes both halves through the dyn wrappers, picking up ValidateAllocator and the retry loop on each. Stats accounting lives inline in each typed body and fires either way.
Macro hygiene: self is evaluated up to twice, ptr up to three times, new_size up to three times. Pass simple lvalues; do not pass expressions with side effects.
Parameters
| Name | Direction | Description |
|---|---|---|
self |
in,out | Typed allocator pointer or Allocator *. |
ptr |
in | Existing allocation pointer, or NULL. |
new_size |
in | Requested new size in bytes. |
Success
Returns the (possibly moved) pointer, or NULL when new_size is zero.
Failure
Returns NULL when reallocation fails.
Usage example (Cross-references)
Usage examples (Cross-references)
- In
Vec.c:95:
}
size old_capacity = (size)vec->capacity;
u8 *ptr = (u8 *)AllocatorRealloc(vec->allocator, vec->data, item_size * (n + 1));
if (!ptr) {- In
Vec.c:157:
LOG_FATAL("vector reduce: capacity * item_size overflows size");
}
u8 *ptr = (u8 *)AllocatorRealloc(vec->allocator, vec->data, item_size * (vec->length + 1));
if (!ptr) {
// Not LOG_SYS_ERROR: allocator failures don't flow through the
- In
BitVec.c:143:
return true;
u64 new_byte_size = BYTES_FOR_BITS(n);
u8 *new_data = (u8 *)AllocatorRealloc(bitvec->allocator, bitvec->data, new_byte_size);
if (!new_data) {- In
BitVec.c:185:
}
u8 *new_data = (u8 *)AllocatorRealloc(bv->allocator, bv->data, new_byte_size);
if (!new_data) {
// A shrink request that the allocator declines to honour is
if (ok) {
p[0] = 'x';
u8 *grown = (u8 *)AllocatorRealloc(alloc, p, 30);
ok = (grown == p) && (grown[0] == 'x');
AllocatorFree(alloc, grown); p[0] = 'h';
p[15] = '!';
u8 *grown = (u8 *)AllocatorRealloc(alloc, p, 200);
// Different bin -> heap must copy into a fresh slot.
ok = (grown != NULL) && (grown != p) && (grown[0] == 'h') && (grown[15] == '!'); p[0] = 'h';
p[15] = 'i';
u8 *grown = (u8 *)AllocatorRealloc(alloc_base, p, 32);
// Grew in place at the same address, with content preserved.
ok = (grown == p) && (grown[0] == 'h') && (grown[15] == 'i'); u8 *b = (u8 *)AllocatorAlloc(alloc_base, 16, true);
(void)b;
(void)AllocatorRealloc(alloc_base, a, 64); // -> LOG_FATAL
return false; // unreachable
}- In
AllocDebug.c:233:
}
u8 *grown = (u8 *)AllocatorRealloc(adbg, p, 200);
ok = ok && (grown != NULL) && (grown[0] == 'h') && (grown[15] == '!');
ok = ok && (DebugAllocatorLiveCount(&dbg) == 1);- In
AllocDebug.c:250:
void *p = AllocatorAlloc(adbg, 24, false);
bool ok = (p != NULL) && (DebugAllocatorLiveCount(&dbg) == 1);
void *nil = AllocatorRealloc(adbg, p, 0);
ok = ok && (nil == NULL) && (DebugAllocatorLiveCount(&dbg) == 0);- In
AllocDebug.c:261:
Allocator *adbg = ALLOCATOR_OF(&dbg);
void *p = AllocatorRealloc(adbg, NULL, 32);
bool ok = (p != NULL) && (DebugAllocatorLiveCount(&dbg) == 1);
if (p) p[63] = 0x6B;
u8 *grown = (u8 *)AllocatorRealloc(adbg, p, 200);
bool ok = (grown != NULL);
ok = ok && (grown[0] == (u8)(0xA0)); p[i] = (u8)(i + 1);
u8 *shrunk = (u8 *)AllocatorRealloc(adbg, p, 8);
bool ok = (shrunk != NULL);
for (u32 i = 0; i < 8; i++)
u8 junk[64];
(void)AllocatorRealloc(adbg, junk, 128); // -> deallocate -> Heap LOG_FATAL
return false; // unreachable
} ptr[0] = 'a';
ptr[63] = 'z';
u8 *grown = (u8 *)AllocatorRealloc(alloc_base, ptr, page * 2);
ok = ok && (grown != NULL);
ok = ok && (grown[0] == 'a') && (grown[63] == 'z'); if (grown) {
grown[page * 2 - 1] = 'q';
u8 *shrunk = (u8 *)AllocatorRealloc(alloc_base, grown, 32);
ok = ok && (shrunk != NULL) && (shrunk[0] == 'a');
if (shrunk) {
Last updated on