package core.alloc.atomic
+//
+// AtomicAllocator wraps another allocator in a mutex,
+// ensuring that every allocation is thread-safe. This
+// is not needed for the general purpose heap allocator,
+// as that already has a thread-safe implementation.
+
use core {sync}
AtomicAllocator :: struct {
package core.alloc.gc
+//
+// "Garbage collection" is not somthing Onyx has. Even things
+// like reference counted pointers is not something Onyx can
+// do, because of Onyx's simpler semantics. That being said,
+// with custom allocators and some careful design, GC is
+// "achievable". This allocator wraps another allocator. With
+// each allocation, a little extra space is allocated to build
+// a linked list of all allocations made. This way, when the
+// memory is done being used, everything can be freed automatically.
+//
+// The `auto` macro makes this allocator very easy to use:
+//
+// core.alloc.gc.auto() {
+// // Every allocation here will automatically be freed
+// }
+
GCState :: struct {
backing_allocator: Allocator;
first: ^GCLink;
package core.alloc.heap
-// Enable this to enable checking for invalid blocks and other corruptions
-// that may happen on the heap, with the added overhead of checking that
-// on every alloc/resize/free.
-Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
-Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory)
// This is the implementation for the general purpose heap allocator.
// It is a simple bump allocator, with a free list. It is not very good
// of the language. You will not make your own instance of the heap
// allocator, since it controls WASM intrinsics such as memory_grow.
+
+
+// Enable this to enable checking for invalid blocks and other corruptions
+// that may happen on the heap, with the added overhead of checking that
+// on every alloc/resize/free.
+Enable_Debug :: #defined( runtime.vars.Enable_Heap_Debug )
+Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memory)
+
#load "core/intrinsics/wasm"
#if runtime.Multi_Threading_Enabled {
package core.alloc.log
-// FIXME: This should use context.logger instead of printf.
+// This allocator simply wraps another allocator and
+// prints every allocation/deallocation made by that
+// allocator.
+#local
Allocation_Action_Strings := str.[
" alloc",
" free",
allocator := cast(^Allocator) data;
res := allocator.func(allocator.data, aa, size, align, oldptr);
- use core { printf }
- printf("{} with size {}, align {}, oldptr {} returns {}\n",
+ use core { tprintf }
+ msg := tprintf("{} with size {}, align {}, oldptr {} returns {}\n",
Allocation_Action_Strings[cast(u32) aa], size, align, oldptr, res);
+ log(.Info, "Core", msg);
+
return res;
}