123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- package mem
- import "core:runtime"
- // NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
- Allocator_Mode :: runtime.Allocator_Mode;
- /*
- Allocator_Mode :: enum byte {
- Alloc,
- Free,
- Free_All,
- Resize,
- Query_Features,
- }
- */
- Allocator_Mode_Set :: runtime.Allocator_Mode_Set;
- /*
- Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
- */
- Allocator_Query_Info :: runtime.Allocator_Query_Info;
- /*
- Allocator_Query_Info :: struct {
- pointer: Maybe(rawptr),
- size: Maybe(int),
- alignment: Maybe(int),
- }
- */
- Allocator_Proc :: runtime.Allocator_Proc;
- /*
- Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
- size, alignment: int,
- old_memory: rawptr, old_size: int, flags: u64 = 0, location := #caller_location) -> rawptr;
- */
- Allocator :: runtime.Allocator;
- /*
- Allocator :: struct {
- procedure: Allocator_Proc,
- data: rawptr,
- }
- */
- DEFAULT_ALIGNMENT :: 2*align_of(rawptr);
- alloc :: inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
- if size == 0 do return nil;
- if allocator.procedure == nil do return nil;
- return allocator.procedure(allocator.data, Allocator_Mode.Alloc, size, alignment, nil, 0, 0, loc);
- }
- free :: inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) {
- if ptr == nil do return;
- if allocator.procedure == nil do return;
- allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, 0, 0, loc);
- }
- free_all :: inline proc(allocator := context.allocator, loc := #caller_location) {
- if allocator.procedure != nil {
- allocator.procedure(allocator.data, Allocator_Mode.Free_All, 0, 0, nil, 0, 0, loc);
- }
- }
- resize :: inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
- if allocator.procedure == nil {
- return nil;
- }
- if new_size == 0 {
- if ptr != nil {
- allocator.procedure(allocator.data, Allocator_Mode.Free, 0, 0, ptr, 0, 0, loc);
- }
- return nil;
- } else if ptr == nil {
- return allocator.procedure(allocator.data, Allocator_Mode.Alloc, new_size, alignment, nil, 0, 0, loc);
- }
- return allocator.procedure(allocator.data, Allocator_Mode.Resize, new_size, alignment, ptr, old_size, 0, loc);
- }
- query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) {
- if allocator.procedure != nil {
- allocator.procedure(allocator.data, Allocator_Mode.Query_Features, 0, 0, &set, 0, 0, loc);
- return set;
- }
- return nil;
- }
- query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_location) -> (props: Allocator_Query_Info) {
- props.pointer = pointer;
- if allocator.procedure != nil {
- allocator.procedure(allocator.data, Allocator_Mode.Query_Info, 0, 0, &props, 0, 0, loc);
- }
- return;
- }
- delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
- free(raw_data(str), allocator, loc);
- }
- delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
- free((^byte)(str), allocator, loc);
- }
- delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
- free(raw_data(array), array.allocator, loc);
- }
- delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
- free(raw_data(array), allocator, loc);
- }
- delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
- raw := transmute(Raw_Map)m;
- delete_slice(raw.hashes);
- free(raw.entries.data, raw.entries.allocator, loc);
- }
- delete :: proc{
- delete_string,
- delete_cstring,
- delete_dynamic_array,
- delete_slice,
- delete_map,
- };
- new :: inline proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
- return new_aligned(T, align_of(T), allocator, loc);
- }
- new_aligned :: inline proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> ^T {
- ptr := (^T)(alloc(size_of(T), alignment, allocator, loc));
- if ptr != nil do ptr^ = T{};
- return ptr;
- }
- new_clone :: inline proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
- ptr := (^T)(alloc(size_of(T), align_of(T), allocator, loc));
- if ptr != nil do ptr^ = data;
- return ptr;
- }
- make_slice :: inline proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
- return make_aligned(T, len, align_of(E), allocator, loc);
- }
- make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
- runtime.make_slice_error_loc(loc, len);
- data := alloc(size_of(E)*len, alignment, allocator, loc);
- if data == nil && size_of(E) != 0 {
- return nil;
- }
- zero(data, size_of(E)*len);
- s := Raw_Slice{data, len};
- return transmute(T)s;
- }
- make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
- return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
- }
- make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
- return make_dynamic_array_len_cap(T, len, len, allocator, loc);
- }
- make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, auto_cast len: int, auto_cast cap: int, allocator := context.allocator, loc := #caller_location) -> T {
- runtime.make_dynamic_array_error_loc(loc, len, cap);
- data := alloc(size_of(E)*cap, align_of(E), allocator, loc);
- s := Raw_Dynamic_Array{data, len, cap, allocator};
- if data == nil && size_of(E) != 0 {
- s.len, s.cap = 0, 0;
- }
- zero(data, size_of(E)*len);
- return transmute(T)s;
- }
- make_map :: proc($T: typeid/map[$K]$E, auto_cast cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
- runtime.make_map_expr_error_loc(loc, cap);
- context.allocator = allocator;
- m: T;
- reserve_map(&m, cap);
- return m;
- }
- make :: proc{
- make_slice,
- make_dynamic_array,
- make_dynamic_array_len,
- make_dynamic_array_len_cap,
- make_map,
- };
- default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> rawptr {
- if old_memory == nil do return alloc(new_size, alignment, allocator, loc);
- if new_size == 0 {
- free(old_memory, allocator, loc);
- return nil;
- }
- if new_size == old_size do return old_memory;
- new_memory := alloc(new_size, alignment, allocator, loc);
- if new_memory == nil do return nil;
- copy(new_memory, old_memory, min(old_size, new_size));
- free(old_memory, allocator, loc);
- return new_memory;
- }
|