documented allocators uses
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 12 Feb 2023 22:37:57 +0000 (16:37 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 12 Feb 2023 22:37:57 +0000 (16:37 -0600)
core/alloc/atomic.onyx
core/alloc/gc.onyx
core/alloc/heap.onyx
core/alloc/logging.onyx

index 3272d3fa66d002a66425055b23334639dd3bc353..2ba02783edd66414fc7b0907986a63440c667396 100644 (file)
@@ -1,5 +1,11 @@
 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 {
index 83eba584907f1fa7498b05b770244d77a22b1528..06693021eafe1deec8cc6bb11357201c9cb9c6b4 100644 (file)
@@ -1,5 +1,21 @@
 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;
index caaee215e454391a8a268deceb00f116180e8ab3..a763142ba077f71fd448a9a0b56ae854f6ad31a9 100644 (file)
@@ -1,10 +1,5 @@
 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
@@ -12,6 +7,14 @@ Enable_Clear_Freed_Memory :: #defined(runtime.vars.Enable_Heap_Clear_Freed_Memor
 // 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 {
index 44295bc4cf333067a38feb102ab0ba01a6eb1c4c..9558f4e8a90d716e377c6454fbddba382e6bb980 100644 (file)
@@ -1,7 +1,10 @@
 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",
@@ -13,10 +16,12 @@ logging_allocator_proc :: (data: rawptr, aa: AllocationAction, size: u32, align:
     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;
 }