summaryrefslogtreecommitdiff
path: root/src/core/allocator.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/allocator.h')
-rw-r--r--src/core/allocator.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/core/allocator.h b/src/core/allocator.h
new file mode 100644
index 0000000..e67a08b
--- /dev/null
+++ b/src/core/allocator.h
@@ -0,0 +1,69 @@
+#ifndef SAND_ALLOCATOR_H
+#define SAND_ALLOCATOR_H
+
+// This module defines a generic allocator interface. All allocations in this
+// family of programs happen through this allocation interface.
+//
+// As references to `SandAllocator`s are passed all around the program, the
+// convention adopted here is to allow single-variable (mainly `a`) names for
+// these.
+
+#include <stddef.h>
+#include <stdbool.h>
+
+typedef struct {
+ // Shall return a new piece of writable and readable memory of size `size` and with alignment `alignment`.
+ // This function may return `NULL` to indicate out-of-memory.
+ // Caller promises to call `deallocate` or `reallocate` on the returned pointer.
+ void *(* allocate)(size_t size, size_t alignment, void *user_data);
+
+ // Shall the allocation made at `old_ptr`.
+ // Unlike with `realloc(3)`, `old_ptr` is not nullable.
+ // This operation is assumed to be infallible, as there is no reasonable way to recover.
+ // FIXME: This should take alignment as well.
+ void (* deallocate)(void *old_ptr, size_t old_size, void *user_data);
+
+ // Resize the allocation at `old_ptr` from `old_size` to `new_size`.
+ // `alignment` is guaranteed to be the same as passed to the original call to `allocate`.
+ // `old_ptr` and `old_size` are guaranteed to be from the last successful invocation of `allocate` or `reallocate`.
+ // This function may return `NULL` to indicate out-of-memory, however `old_ptr` should still remain valid in that case.
+ // The struct member itself may be `NULL`, in which case a default implementation is used.
+ void *(* reallocate)(void *old_ptr, size_t old_size, size_t new_size, size_t alignment, void *user_data);
+
+ // Custom data which is passed to every function in the interface. The
+ // allocator can use this for extra metadata it needs to keep.
+ void *user_data;
+} SandAllocator;
+
+
+// Allocates a chunk of memory with the given size and alignment.
+// Returns `NULL` on failure.
+// Caller assumes ownership of returned pointer, must free with `sand_deallocate`.
+void *sand_allocate_aligned(SandAllocator *, size_t size, size_t alignment);
+
+// Same as `sand_allocate_aligned` but with default alignment.
+void *sand_allocate(SandAllocator *, size_t size);
+
+// Resize the allocation at `old_ptr` from `old_size` to `new_size`.
+// `alignment` is guaranteed to be the same as passed to the original call to `allocate`.
+// Returns a new pointer or `NULL` if reallocation fails.
+// If `NULL` is returned, `old_ptr` remains valid.
+// Caller assumes ownership of returned pointer (or retains ownership of old pointer).
+void *sand_reallocate_aligned(SandAllocator *, void *old_ptr, size_t old_size, size_t new_size, size_t alignment);
+
+// Same as `sand_reallocate_aligned` but with default alignment.
+void *sand_reallocate(SandAllocator *, void *old_ptr, size_t old_size, size_t new_size);
+
+// Frees `old_ptr`.
+// `old_ptr` is nullable, in which case `old_size` is ignored.
+// `old_size` must match the size passed to last call to `sand_allocate` or `sand_reallocate`.
+void sand_deallocate(SandAllocator *, void *old_ptr, size_t old_size);
+
+// The following are only intended to be used by allocator implementations.
+bool sand_is_valid_alignment(size_t alignment);
+bool sand_pointer_is_aligned(void *pointer, size_t alignment);
+void *sand_align_pointer_forward(void *ptr, size_t alignment);
+bool sand_size_is_aligned(size_t n, size_t alignment);
+size_t sand_align_size_forward(size_t n, size_t alignment);
+
+#endif