mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Unify new/make the internal logic between runtime and mem
This commit is contained in:
+41
-28
@@ -207,51 +207,54 @@ delete :: proc{
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
|
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) {
|
||||||
return new_aligned(T, align_of(T), allocator, loc);
|
return new_aligned(T, align_of(T), allocator, loc);
|
||||||
}
|
}
|
||||||
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> ^T {
|
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
|
||||||
ptr := (^T)(alloc(size_of(T), alignment, allocator, loc));
|
data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
|
||||||
if ptr != nil { ptr^ = T{}; }
|
t = (^T)(raw_data(data));
|
||||||
return ptr;
|
return;
|
||||||
}
|
}
|
||||||
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
|
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
|
||||||
ptr := (^T)(alloc(size_of(T), align_of(T), allocator, loc));
|
data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
|
||||||
if ptr != nil { ptr^ = data; }
|
t = (^T)(raw_data(data));
|
||||||
return ptr;
|
if t != nil {
|
||||||
|
t^ = data;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFAULT_RESERVE_CAPACITY :: 16;
|
||||||
|
|
||||||
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) {
|
||||||
|
runtime.make_slice_error_loc(loc, len);
|
||||||
|
data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return;
|
||||||
|
if data == nil && size_of(E) != 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slice = transmute(T)Raw_Slice{raw_data(data), len};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
||||||
return make_aligned(T, len, align_of(E), allocator, loc);
|
return make_aligned(T, len, align_of(E), allocator, loc);
|
||||||
}
|
}
|
||||||
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
||||||
runtime.make_slice_error_loc(loc, len);
|
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
|
||||||
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 {
|
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
|
||||||
return make_dynamic_array_len_cap(T, 0, 16, allocator, loc);
|
|
||||||
}
|
|
||||||
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> T {
|
|
||||||
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
||||||
}
|
}
|
||||||
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {
|
||||||
runtime.make_dynamic_array_error_loc(loc, len, cap);
|
runtime.make_dynamic_array_error_loc(loc, len, cap);
|
||||||
data := alloc(size_of(E)*cap, align_of(E), allocator, loc);
|
data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return;
|
||||||
s := Raw_Dynamic_Array{data, len, cap, allocator};
|
s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator};
|
||||||
if data == nil && size_of(E) != 0 {
|
if data == nil && size_of(E) != 0 {
|
||||||
s.len, s.cap = 0, 0;
|
s.len, s.cap = 0, 0;
|
||||||
}
|
}
|
||||||
zero(data, size_of(E)*len);
|
array = transmute(T)s;
|
||||||
return transmute(T)s;
|
return;
|
||||||
}
|
}
|
||||||
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 16, allocator := context.allocator, loc := #caller_location) -> T {
|
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
|
||||||
runtime.make_map_expr_error_loc(loc, cap);
|
runtime.make_map_expr_error_loc(loc, cap);
|
||||||
context.allocator = allocator;
|
context.allocator = allocator;
|
||||||
|
|
||||||
@@ -259,6 +262,15 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 16, allocator := cont
|
|||||||
reserve_map(&m, cap);
|
reserve_map(&m, cap);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) {
|
||||||
|
runtime.make_slice_error_loc(loc, len);
|
||||||
|
data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return;
|
||||||
|
if data == nil && size_of(E) != 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mp = cast(T)raw_data(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
make :: proc{
|
make :: proc{
|
||||||
make_slice,
|
make_slice,
|
||||||
@@ -266,6 +278,7 @@ make :: proc{
|
|||||||
make_dynamic_array_len,
|
make_dynamic_array_len,
|
||||||
make_dynamic_array_len_cap,
|
make_dynamic_array_len_cap,
|
||||||
make_map,
|
make_map,
|
||||||
|
make_multi_pointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -114,12 +114,13 @@ Scratch_Allocator :: struct {
|
|||||||
leaked_allocations: [dynamic][]byte,
|
leaked_allocations: [dynamic][]byte,
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) {
|
scratch_allocator_init :: proc(s: ^Scratch_Allocator, size: int, backup_allocator := context.allocator) -> Allocator_Error {
|
||||||
s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator);
|
s.data = make_aligned([]byte, size, 2*align_of(rawptr), backup_allocator) or_return;
|
||||||
s.curr_offset = 0;
|
s.curr_offset = 0;
|
||||||
s.prev_allocation = nil;
|
s.prev_allocation = nil;
|
||||||
s.backup_allocator = backup_allocator;
|
s.backup_allocator = backup_allocator;
|
||||||
s.leaked_allocations.allocator = backup_allocator;
|
s.leaked_allocations.allocator = backup_allocator;
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {
|
scratch_allocator_destroy :: proc(s: ^Scratch_Allocator) {
|
||||||
@@ -188,7 +189,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
return ptr, err;
|
return ptr, err;
|
||||||
}
|
}
|
||||||
if s.leaked_allocations == nil {
|
if s.leaked_allocations == nil {
|
||||||
s.leaked_allocations = make([dynamic][]byte, a);
|
s.leaked_allocations, err = make([dynamic][]byte, a);
|
||||||
}
|
}
|
||||||
append(&s.leaked_allocations, ptr);
|
append(&s.leaked_allocations, ptr);
|
||||||
|
|
||||||
|
|||||||
@@ -170,18 +170,22 @@ delete :: proc{
|
|||||||
// return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
|
// return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
|
||||||
@builtin
|
@builtin
|
||||||
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
|
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
|
||||||
ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
|
return new_aligned(T, align_of(T), allocator, loc);
|
||||||
return (^T)(ptr), err;
|
}
|
||||||
|
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
|
||||||
|
data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
|
||||||
|
t = (^T)(raw_data(data));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
|
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_second {
|
||||||
ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
|
data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return;
|
||||||
res := (^T)(ptr);
|
t = (^T)(raw_data(data));
|
||||||
if ptr != nil && err != .Out_Of_Memory {
|
if t != nil {
|
||||||
res^ = data;
|
t^ = data;
|
||||||
}
|
}
|
||||||
return res, err;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_RESERVE_CAPACITY :: 16;
|
DEFAULT_RESERVE_CAPACITY :: 16;
|
||||||
@@ -196,33 +200,30 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat
|
|||||||
return transmute(T)s, err;
|
return transmute(T)s, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@(builtin)
|
||||||
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_aligned(T, len, align_of(E), allocator, loc);
|
return make_aligned(T, len, align_of(E), allocator, loc);
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
@builtin
|
|
||||||
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
|
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
@builtin
|
|
||||||
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
@builtin
|
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second {
|
||||||
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
|
||||||
make_dynamic_array_error_loc(loc, len, cap);
|
make_dynamic_array_error_loc(loc, len, cap);
|
||||||
data, err := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
|
data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return;
|
||||||
s := Raw_Dynamic_Array{data, len, cap, allocator};
|
s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator};
|
||||||
if data == nil && size_of(E) != 0 {
|
if data == nil && size_of(E) != 0 {
|
||||||
s.len, s.cap = 0, 0;
|
s.len, s.cap = 0, 0;
|
||||||
}
|
}
|
||||||
return transmute(T)s, err;
|
array = transmute(T)s;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
@builtin
|
|
||||||
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
|
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
|
||||||
make_map_expr_error_loc(loc, cap);
|
make_map_expr_error_loc(loc, cap);
|
||||||
context.allocator = allocator;
|
context.allocator = allocator;
|
||||||
@@ -231,6 +232,17 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = DEFAULT_RESERVE_CAPAC
|
|||||||
reserve_map(&m, cap);
|
reserve_map(&m, cap);
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@(builtin)
|
||||||
|
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) #optional_second {
|
||||||
|
make_slice_error_loc(loc, len);
|
||||||
|
data := mem_alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return;
|
||||||
|
if data == nil && size_of(E) != 0 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mp = cast(T)raw_data(data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only)
|
// The make built-in procedure allocates and initializes a value of type slice, dynamic array, or map (only)
|
||||||
// Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the
|
// Similar to new, the first argument is a type, not a value. Unlike new, make's return type is the same as the
|
||||||
@@ -243,6 +255,7 @@ make :: proc{
|
|||||||
make_dynamic_array_len,
|
make_dynamic_array_len,
|
||||||
make_dynamic_array_len_cap,
|
make_dynamic_array_len_cap,
|
||||||
make_map,
|
make_map,
|
||||||
|
make_multi_pointer,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user