split up mem_allocator examples

This commit is contained in:
2026-07-12 00:39:39 +02:00
parent fbbbfa454c
commit cff9e9500f
7 changed files with 405 additions and 374 deletions
+5 -372
View File
@@ -1,376 +1,9 @@
mem :: import "@std/mem"
_probe_count func(context ?*mut anyopaque) void {
if context |raw| {
counts *mut usize :: ptr_cast(usize, raw)
counts[0] += 1
}
}
_probe_alloc func(context ?*mut anyopaque, _ usize, _ usize) ?*mut u8 {
_probe_count(context)
return none
}
_probe_realloc func(context ?*mut anyopaque, _ ?*mut u8, _ usize, _ usize, _ usize) ?*mut u8 {
_probe_count(context)
return none
}
_probe_free func(context ?*mut anyopaque, _ ?*mut u8, _ usize, _ usize) void {
_probe_count(context)
}
_probe_vtable mem.AllocatorVTable :: mem.AllocatorVTable {
alloc = _probe_alloc,
realloc = _probe_realloc,
free = _probe_free,
}
TaskList :: struct {
ids ?[]mut i32
priorities ?[]mut i32
durations ?[]mut i32
len usize
capacity usize
allocator mem.Allocator
}
task_list_init func(allocator mem.Allocator) TaskList {
return TaskList {
ids = none,
priorities = none,
durations = none,
len = 0,
capacity = 0,
allocator = allocator,
}
}
alloc_i32s func(allocator mem.Allocator, count usize) ?[]mut i32 {
fallback [1]mut i32 = undefined
failed bool = false
values []mut i32 = mem.alloc(i32, allocator, count) catch |_| {
failed = true
yield (&fallback).ptr[..0]
}
if (failed) return none
return values
}
free_i32s func(allocator mem.Allocator, values ?[]mut i32) void {
if values |slice| {
mem.raw_free(allocator, ptr_cast(u8, slice.ptr), slice.len * size_of(i32), align_of(i32))
}
}
task_list_reserve func(list @mut TaskList, capacity usize) bool {
if capacity <= list.capacity {
return true
}
new_ids ?[]mut i32 = alloc_i32s(list.allocator, capacity)
new_priorities ?[]mut i32 = alloc_i32s(list.allocator, capacity)
new_durations ?[]mut i32 = alloc_i32s(list.allocator, capacity)
if (new_ids and new_priorities and new_durations) |ids, priorities, durations| {
if list.len > 0 {
if (list.ids and list.priorities and list.durations) |old_ids, old_priorities, old_durations| {
i usize = 0
while i < list.len : i += 1 {
ids[i] = old_ids[i]
priorities[i] = old_priorities[i]
durations[i] = old_durations[i]
}
} else {
free_i32s(list.allocator, new_ids)
free_i32s(list.allocator, new_priorities)
free_i32s(list.allocator, new_durations)
return false
}
}
free_i32s(list.allocator, list.ids)
free_i32s(list.allocator, list.priorities)
free_i32s(list.allocator, list.durations)
list.ids = new_ids
list.priorities = new_priorities
list.durations = new_durations
list.capacity = capacity
return true
}
free_i32s(list.allocator, new_ids)
free_i32s(list.allocator, new_priorities)
free_i32s(list.allocator, new_durations)
return false
}
task_list_push func(list @mut TaskList, id i32, priority i32, duration i32) bool {
if list.len == list.capacity {
new_capacity usize = 2
if list.capacity != 0 {
new_capacity = list.capacity * 2
}
if task_list_reserve(list, new_capacity) == false {
return false
}
}
if (list.ids and list.priorities and list.durations) |ids, priorities, durations| {
index usize = list.len
ids[index] = id
priorities[index] = priority
durations[index] = duration
list.len += 1
return true
}
return false
}
task_score func(priority i32, duration i32) i32 {
return priority * 10 - duration
}
task_list_best_id func(list @mut TaskList) i32 {
if list.len == 0 {
return -1
}
if (list.ids and list.priorities and list.durations) |ids, priorities, durations| {
best_index usize = 0
best_score i32 = task_score(priorities[0], durations[0])
i usize = 1
while i < list.len : i += 1 {
score i32 = task_score(priorities[i], durations[i])
if score > best_score {
best_score = score
best_index = i
}
}
return ids[best_index]
}
return -1
}
task_list_total_duration func(list @mut TaskList) i32 {
total i32 = 0
if list.durations |durations| {
i usize = 0
while i < list.len : i += 1 {
total += durations[i]
}
}
return total
}
task_list_deinit func(list @mut TaskList) void {
free_i32s(list.allocator, list.ids)
free_i32s(list.allocator, list.priorities)
free_i32s(list.allocator, list.durations)
list.ids = none
list.priorities = none
list.durations = none
list.len = 0
list.capacity = 0
}
main func() i32 {
if (size_of(mem.Allocator) != 16) return 31
typed_result i32 :: typed_allocator_test()
if (typed_result != 0) return typed_result
first_calls [1]mut usize = [0]
second_calls [1]mut usize = [0]
first_allocator mem.Allocator :: mem.Allocator {
context = (&first_calls).ptr,
vtable = &_probe_vtable,
}
second_allocator mem.Allocator :: mem.Allocator {
context = (&second_calls).ptr,
vtable = &_probe_vtable,
}
raw_result i32 :: raw_allocator_test()
if (raw_result != 0) return raw_result
_ = mem.raw_alloc(first_allocator, 1, 1)
_ = mem.raw_realloc(first_allocator, none, 0, 1, 1)
mem.raw_free(first_allocator, none, 0, 1)
_ = mem.raw_alloc(second_allocator, 1, 1)
if (first_calls[0] != 3 or second_calls[0] != 1) return 32
i32_fallback [1]mut i32 = undefined
empty_failed bool = false
empty []mut i32 = mem.alloc(i32, first_allocator, 0) catch |_| {
empty_failed = true
yield (&i32_fallback).ptr[..0]
}
if (empty_failed or empty.len != 0 or first_calls[0] != 3) return 34
zero_sized_fallback [1]mut [0]u8 = undefined
zero_sized_failed bool = false
zero_sized []mut [0]u8 = mem.alloc([0]u8, first_allocator, 3) catch |_| {
zero_sized_failed = true
yield (&zero_sized_fallback).ptr[..0]
}
if (zero_sized_failed or zero_sized.len != 3 or first_calls[0] != 3) return 36
_ = zero_sized[2]
u64_fallback [1]mut u64 = undefined
overflow_fallback_failed bool = false
overflow_fallback []mut u64 = mem.alloc(u64, first_allocator, 0) catch |_| {
overflow_fallback_failed = true
yield (&u64_fallback).ptr[..0]
}
if (overflow_fallback_failed) return 37
overflow_failed bool = false
_ = mem.alloc(u64, first_allocator, max_value(usize)) catch |_| {
overflow_failed = true
yield overflow_fallback
}
if (overflow_failed == false or first_calls[0] != 3) return 40
typed_failed bool = false
typed []mut i32 = mem.alloc(i32, mem.c_allocator, 4) catch |_| {
typed_failed = true
yield (&i32_fallback).ptr[..0]
}
if (typed_failed) return 38
defer mem.raw_free(mem.c_allocator, ptr_cast(u8, typed.ptr), typed.len * size_of(i32), align_of(i32))
typed[0] = 10
typed[3] = 20
if (typed[0] + typed[3] != 30) return 39
resized ?*mut u8 = mem.raw_realloc(mem.c_allocator, none, 0, 4, 1)
if resized |bytes| {
bytes[0] = 10
bytes[1] = 20
bytes[2] = 30
bytes[3] = 40
} else {
return 20
}
grown ?*mut u8 = mem.raw_realloc(mem.c_allocator, resized, 4, 8, 1)
if grown |bytes| {
resized = grown
if bytes[0] != 10 or bytes[1] != 20 or bytes[2] != 30 or bytes[3] != 40 {
mem.raw_free(mem.c_allocator, grown, 8, 1)
return 21
}
} else {
mem.raw_free(mem.c_allocator, resized, 4, 1)
return 22
}
shrunk ?*mut u8 = mem.raw_realloc(mem.c_allocator, resized, 8, 2, 1)
if shrunk |bytes| {
resized = shrunk
if bytes[0] != 10 or bytes[1] != 20 {
mem.raw_free(mem.c_allocator, shrunk, 2, 1)
return 23
}
} else {
mem.raw_free(mem.c_allocator, resized, 8, 1)
return 24
}
invalid ?*mut u8 = mem.raw_realloc(mem.c_allocator, resized, 2, 4, 24)
if invalid |memory| {
mem.raw_free(mem.c_allocator, memory, 4, 24)
mem.raw_free(mem.c_allocator, resized, 2, 1)
return 25
}
if resized |bytes| {
if bytes[0] != 10 or bytes[1] != 20 {
mem.raw_free(mem.c_allocator, resized, 2, 1)
return 26
}
}
resized = mem.raw_realloc(mem.c_allocator, resized, 2, 0, 1)
if resized |memory| {
mem.raw_free(mem.c_allocator, memory, 0, 1)
return 27
}
over_aligned ?*mut u8 = mem.raw_alloc(mem.c_allocator, 4, 32)
if over_aligned |bytes| {
bytes[0] = 11
bytes[1] = 22
} else {
return 28
}
over_aligned_grown ?*mut u8 = mem.raw_realloc(mem.c_allocator, over_aligned, 4, 8, 32)
if over_aligned_grown |bytes| {
if bytes[0] != 11 or bytes[1] != 22 {
mem.raw_free(mem.c_allocator, over_aligned_grown, 8, 32)
return 29
}
mem.raw_free(mem.c_allocator, over_aligned_grown, 8, 32)
} else {
mem.raw_free(mem.c_allocator, over_aligned, 4, 32)
return 30
}
zero_alignment ?*mut u8 = mem.raw_alloc(mem.c_allocator, 8, 0)
if zero_alignment |memory| {
mem.raw_free(mem.c_allocator, memory, 8, 0)
return 1
}
bad_alignment ?*mut u8 = mem.raw_alloc(mem.c_allocator, 8, 24)
if bad_alignment |memory| {
mem.raw_free(mem.c_allocator, memory, 8, 24)
return 2
}
aligned ?*mut u8 = mem.raw_alloc(mem.c_allocator, 64, 32)
defer mem.raw_free(mem.c_allocator, aligned, 64, 32)
if aligned |bytes| {
bytes[0] = 1
bytes[63] = 2
if bytes[0] + bytes[63] != 3 {
return 4
}
} else {
return 3
}
tasks TaskList = task_list_init(mem.c_allocator)
defer task_list_deinit(&tasks)
if task_list_push(&tasks, 101, 3, 5) == false {
return 5
}
if tasks.capacity != 2 {
return 6
}
if task_list_push(&tasks, 202, 1, 4) == false {
return 7
}
if tasks.capacity != 2 {
return 8
}
if task_list_push(&tasks, 303, 4, 8) == false {
return 9
}
if tasks.capacity != 4 {
return 10
}
if tasks.len != 3 {
return 11
}
if task_list_best_id(&tasks) != 303 {
return 12
}
if task_list_total_duration(&tasks) != 17 {
return 13
}
return 0
return task_list_test()
}