diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 171 | 
1 files changed, 171 insertions, 0 deletions
diff --git a/src/alloc.c b/src/alloc.c new file mode 100644 index 0000000..2fb7a78 --- /dev/null +++ b/src/alloc.c @@ -0,0 +1,171 @@ +#include "alloc.h" +#include "maths.h" +#include "platform.h" +#include <assert.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +void *vgltf_allocator_allocate(struct vgltf_allocator *allocator, size_t size) { +  assert(allocator); +  return allocator->allocate(size, allocator->ctx); +} +void *vgltf_allocator_allocate_aligned(struct vgltf_allocator *allocator, +                                     size_t alignment, size_t size) { +  assert(allocator); +  return allocator->allocate_aligned(alignment, size, allocator->ctx); +} +void *vgltf_allocator_allocate_array(struct vgltf_allocator *allocator, +                                   size_t count, size_t item_size) { +  assert(allocator); +  return allocator->allocate_array(count, item_size, allocator->ctx); +} +void *vgltf_allocator_reallocate(struct vgltf_allocator *allocator, void *ptr, +                               size_t old_size, size_t new_size) { +  assert(allocator); +  return allocator->reallocate(ptr, old_size, new_size, allocator->ctx); +} +void vgltf_allocator_free(struct vgltf_allocator *allocator, void *ptr) { +  assert(allocator); +  allocator->free(ptr, allocator->ctx); +} + +static void *memory_allocate(size_t size, void *ctx) { +  (void)ctx; +  void *ptr = malloc(size); +  if (!ptr) { +    VGLTF_PANIC("Couldn't allocate memory (out of mem?)"); +  } +  return ptr; +} + +static void *memory_allocate_aligned(size_t alignment, size_t size, void *ctx) { +  (void)ctx; +#ifdef VGLTF_PLATFORM_WINDOWS +  void *ptr = _aligned_malloc(size, VGLTF_MAX(alignment, sizeof(void *))); +#else +  void *ptr = aligned_alloc(VGLTF_MAX(alignment, sizeof(void *)), size); +#endif +  if (!ptr) { +    VGLTF_PANIC("Couldn't allocate aligned memory (out of mem?)"); +  } +  return ptr; +} + +static void *memory_allocate_array(size_t count, size_t item_size, void *ctx) { +  (void)ctx; +  void *ptr = calloc(count, item_size); +  if (!ptr) { +    VGLTF_PANIC("Couldn't allocate memory (out of mem?)"); +  } +  return ptr; +} + +static void *memory_reallocate(void *ptr, size_t old_size, size_t new_size, +                               void *ctx) { +  (void)old_size; +  (void)ctx; +  ptr = realloc(ptr, new_size); +  if (!ptr) { +    VGLTF_PANIC("Couldn't allocate memory (out of mem?)"); +  } +  return ptr; +} + +static void memory_free(void *ptr, void *ctx) { +  (void)ctx; +  free(ptr); +} + +thread_local struct vgltf_allocator system_allocator = { +    .allocate = memory_allocate, +    .allocate_aligned = memory_allocate_aligned, +    .allocate_array = memory_allocate_array, +    .reallocate = memory_reallocate, +    .free = memory_free}; + +void vgltf_arena_init(struct vgltf_allocator *allocator, struct vgltf_arena *arena, +                    size_t size) { +  assert(allocator); +  assert(arena); +  arena->size = 0; +  arena->capacity = size; +  arena->data = vgltf_allocator_allocate(allocator, size); +} +void vgltf_arena_deinit(struct vgltf_allocator *allocator, +                      struct vgltf_arena *arena) { +  assert(allocator); +  assert(arena); +  vgltf_allocator_free(allocator, arena->data); +} +void *vgltf_arena_allocate(struct vgltf_arena *arena, size_t size) { +  assert(arena); +  assert(arena->size + size <= arena->capacity); +  void *ptr = arena->data + arena->size; +  arena->size += size; +  return ptr; +} + +void *vgltf_arena_allocate_array(struct vgltf_arena *arena, size_t count, +                               size_t item_size) { +  assert(arena); +  void *ptr = vgltf_arena_allocate(arena, count * item_size); +  memset(ptr, 0, count * item_size); +  return ptr; +} + +void vgltf_arena_reset(struct vgltf_arena *arena) { +  assert(arena); +  arena->size = 0; +} + +static void *arena_allocator_allocate(size_t size, void *ctx) { +  assert(ctx); +  return vgltf_arena_allocate(ctx, size); +} +static void *arena_allocator_allocate_aligned(size_t alignment, size_t size, +                                              void *ctx) { +  assert(ctx); +  if (alignment < sizeof(void *) || (alignment & (alignment - 1)) != 0) { +    return NULL; +  } + +  void *ptr = vgltf_arena_allocate(ctx, size + alignment - 1 + sizeof(void *)); +  if (!ptr) { +    return NULL; +  } + +  return (void *)(((uintptr_t)ptr + sizeof(void *) + alignment - 1) & +                  ~(alignment - 1)); +} + +static void *arena_allocator_allocate_array(size_t count, size_t item_size, +                                            void *ctx) { +  assert(ctx); +  return vgltf_arena_allocate_array(ctx, count, item_size); +} + +static void *arena_allocator_reallocate(void *ptr, size_t old_size, +                                        size_t new_size, void *ctx) { +  assert(ptr); +  assert(ctx); + +  void *new_ptr = vgltf_arena_allocate(ctx, new_size); +  memcpy(new_ptr, ptr, old_size); +  return new_ptr; +} + +static void arena_allocator_free(void *ptr, void *ctx) { +  assert(ctx); +  (void)ptr; +} + +struct vgltf_allocator vgltf_arena_allocator(struct vgltf_arena *arena) { +  return (struct vgltf_allocator){ +      .ctx = arena, +      .allocate = arena_allocator_allocate, +      .allocate_aligned = arena_allocator_allocate_aligned, +      .allocate_array = arena_allocator_allocate_array, +      .reallocate = arena_allocator_reallocate, +      .free = arena_allocator_free}; +}  | 
