/** * Clear all entries from the memory pool except * for @a keep of the given @a size. The pointer * returned should be a buffer of @a new_size where * the first @a copy_bytes are from @a keep. * * @param pool memory pool to use for the operation * @param keep pointer to the entry to keep (maybe NULL) * @param copy_bytes how many bytes need to be kept at this address * @param new_size how many bytes should the allocation we return have? * (should be larger or equal to @a copy_bytes) * @return addr new address of @a keep (if it had to change) */ void * MHD_pool_reset (struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size) { if (NULL != keep) { if (keep != pool->memory) { memmove (pool->memory, keep, copy_bytes); keep = pool->memory; } } pool->end = pool->size; /* technically not needed, but safer to zero out */ memset (&pool->memory[copy_bytes], 0, pool->size - copy_bytes); if (NULL != keep) pool->pos = ROUND_TO_ALIGN (new_size); return keep; }
/** * Clear all entries from the memory pool except * for "keep" of the given "size". * * @param keep pointer to the entry to keep (maybe NULL) * @param size how many bytes need to be kept at this address * @return addr new address of "keep" (if it had to change) */ void * MHD_pool_reset (struct MemoryPool *pool, void *keep, size_t size) { size = ROUND_TO_ALIGN (size); if (keep != NULL) { if (keep != pool->memory) { memmove (pool->memory, keep, size); keep = pool->memory; } pool->pos = size; } pool->end = pool->size; return keep; }
/** * Reallocate a block of memory obtained from the pool. * This is particularly efficient when growing or * shrinking the block that was last (re)allocated. * If the given block is not the most recently * (re)allocated block, the memory of the previous * allocation may be leaked until the pool is * destroyed (and copying the data maybe required). * * @param pool memory pool to use for the operation * @param old the existing block * @param old_size the size of the existing block * @param new_size the new size of the block * @return new address of the block, or * NULL if the pool cannot support @a new_size * bytes (old continues to be valid for @a old_size) */ void * MHD_pool_reallocate (struct MemoryPool *pool, void *old, size_t old_size, size_t new_size) { void *ret; size_t asize; asize = ROUND_TO_ALIGN (new_size); if ( (0 == asize) && (0 != new_size) ) return NULL; /* new_size too close to SIZE_MAX */ if ((pool->end < old_size) || (pool->end < asize)) return NULL; /* unsatisfiable or bogus request */ if ( (pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old) ) { /* was the previous allocation - optimize! */ if (pool->pos + asize - old_size <= pool->end) { /* fits */ pool->pos += asize - old_size; if (asize < old_size) /* shrinking - zero again! */ memset (&pool->memory[pool->pos], 0, old_size - asize); return old; } /* does not fit */ return NULL; } if (asize <= old_size) return old; /* cannot shrink, no need to move */ if ((pool->pos + asize >= pool->pos) && (pool->pos + asize <= pool->end)) { /* fits */ ret = &pool->memory[pool->pos]; memmove (ret, old, old_size); pool->pos += asize; return ret; } /* does not fit */ return NULL; }
/** * Allocate size bytes from the pool. * @return NULL if the pool cannot support size more * bytes */ void * MHD_pool_allocate (struct MemoryPool *pool, size_t size, int from_end) { void *ret; size = ROUND_TO_ALIGN (size); if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos)) return NULL; if (from_end == MHD_YES) { ret = &pool->memory[pool->end - size]; pool->end -= size; } else { ret = &pool->memory[pool->pos]; pool->pos += size; } return ret; }
/** * Allocate size bytes from the pool. * * @param pool memory pool to use for the operation * @param size number of bytes to allocate * @param from_end allocate from end of pool (set to #MHD_YES); * use this for small, persistent allocations that * will never be reallocated * @return NULL if the pool cannot support size more * bytes */ void * MHD_pool_allocate (struct MemoryPool *pool, size_t size, int from_end) { void *ret; size_t asize; asize = ROUND_TO_ALIGN (size); if ( (0 == asize) && (0 != size) ) return NULL; /* size too close to SIZE_MAX */ if ((pool->pos + asize > pool->end) || (pool->pos + asize < pool->pos)) return NULL; if (from_end == MHD_YES) { ret = &pool->memory[pool->end - asize]; pool->end -= asize; } else { ret = &pool->memory[pool->pos]; pool->pos += asize; } return ret; }