From 26a2b3ce947f6a3492cbf380cb2ada68479a1600 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 12 Feb 2023 16:37:57 -0600 Subject: [PATCH] documented allocators uses --- core/alloc/atomic.onyx | 6 ++++++ core/alloc/gc.onyx | 16 ++++++++++++++++ core/alloc/heap.onyx | 13 ++++++++----- core/alloc/logging.onyx | 11 ++++++++--- 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/core/alloc/atomic.onyx b/core/alloc/atomic.onyx index 3272d3fa..2ba02783 100644 --- a/core/alloc/atomic.onyx +++ b/core/alloc/atomic.onyx @@ -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 { diff --git a/core/alloc/gc.onyx b/core/alloc/gc.onyx index 83eba584..06693021 100644 --- a/core/alloc/gc.onyx +++ b/core/alloc/gc.onyx @@ -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; diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index caaee215..a763142b 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -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 { diff --git a/core/alloc/logging.onyx b/core/alloc/logging.onyx index 44295bc4..9558f4e8 100644 --- a/core/alloc/logging.onyx +++ b/core/alloc/logging.onyx @@ -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; } -- 2.25.1