mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-15 23:51:25 -07:00
[mem]: Document alloc.odin
This commit is contained in:
+530
-47
@@ -2,66 +2,272 @@ package mem
|
||||
|
||||
import "base: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.
|
||||
//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.
|
||||
|
||||
/*
|
||||
A request to allocator procedure.
|
||||
|
||||
This type represents a type of allocation request made to an allocator
|
||||
procedure. There is one allocator procedure per allocator, and this value is
|
||||
used to discriminate between different functions of the allocator.
|
||||
|
||||
The type is defined as follows:
|
||||
|
||||
Allocator_Mode :: enum byte {
|
||||
Alloc,
|
||||
Alloc_Non_Zeroed,
|
||||
Free,
|
||||
Free_All,
|
||||
Resize,
|
||||
Resize_Non_Zeroed,
|
||||
Query_Features,
|
||||
}
|
||||
|
||||
Depending on which value is used, the allocator procedure will perform different
|
||||
functions:
|
||||
|
||||
- `Alloc`: Allocates a memory region with a given `size` and `alignment`.
|
||||
- `Alloc_Non_Zeroed`: Same as `Alloc` without explicit zero-initialization of
|
||||
the memory region.
|
||||
- `Free`: Free a memory region located at address `ptr` with a given `size`.
|
||||
- `Free_All`: Free all memory allocated using this allocator.
|
||||
- `Resize`: Resize a memory region located at address `old_ptr` with size
|
||||
`old_size` to be `size` bytes in length and have the specified `alignment`,
|
||||
in case a re-alllocation occurs.
|
||||
- `Resize_Non_Zeroed`: Same as `Resize`, without explicit zero-initialization.
|
||||
|
||||
*/
|
||||
Allocator_Mode :: runtime.Allocator_Mode
|
||||
/*
|
||||
Allocator_Mode :: enum byte {
|
||||
Alloc,
|
||||
Free,
|
||||
Free_All,
|
||||
Resize,
|
||||
Query_Features,
|
||||
Alloc_Non_Zeroed,
|
||||
Resize_Non_Zeroed,
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
A set of allocator features.
|
||||
|
||||
This type represents values that contain a set of features an allocator has.
|
||||
Currently the type is defined as follows:
|
||||
|
||||
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
|
||||
*/
|
||||
Allocator_Mode_Set :: runtime.Allocator_Mode_Set
|
||||
/*
|
||||
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode];
|
||||
*/
|
||||
|
||||
/*
|
||||
Allocator information.
|
||||
|
||||
This type represents information about a given allocator at a specific point
|
||||
in time. Currently the type is defined as follows:
|
||||
|
||||
Allocator_Query_Info :: struct {
|
||||
pointer: rawptr,
|
||||
size: Maybe(int),
|
||||
alignment: Maybe(int),
|
||||
}
|
||||
|
||||
- `pointer`: Pointer to a backing buffer.
|
||||
- `size`: Size of the backing buffer.
|
||||
- `alignment`: The allocator's alignment.
|
||||
|
||||
If not applicable, any of these fields may be `nil`.
|
||||
*/
|
||||
Allocator_Query_Info :: runtime.Allocator_Query_Info
|
||||
/*
|
||||
Allocator_Query_Info :: struct {
|
||||
pointer: rawptr,
|
||||
size: Maybe(int),
|
||||
alignment: Maybe(int),
|
||||
}
|
||||
*/
|
||||
|
||||
Allocator_Error :: runtime.Allocator_Error
|
||||
/*
|
||||
Allocator_Error :: enum byte {
|
||||
None = 0,
|
||||
Out_Of_Memory = 1,
|
||||
Invalid_Pointer = 2,
|
||||
Invalid_Argument = 3,
|
||||
Mode_Not_Implemented = 4,
|
||||
}
|
||||
An allocation request error.
|
||||
|
||||
This type represents error values the allocators may return upon requests.
|
||||
|
||||
Allocator_Error :: enum byte {
|
||||
None = 0,
|
||||
Out_Of_Memory = 1,
|
||||
Invalid_Pointer = 2,
|
||||
Invalid_Argument = 3,
|
||||
Mode_Not_Implemented = 4,
|
||||
}
|
||||
|
||||
The meaning of the errors is as follows:
|
||||
|
||||
- `None`: No error.
|
||||
- `Out_Of_Memory`: Either:
|
||||
1. The allocator has ran out of the backing buffer, or the requested
|
||||
allocation size is too large to fit into a backing buffer.
|
||||
2. The operating system error during memory allocation.
|
||||
3. The backing allocator was used to allocate a new backing buffer and the
|
||||
backing allocator returned Out_Of_Memory.
|
||||
- `Invalid_Pointer`: The pointer referring to a memory region does not belong
|
||||
to any of the allocators backing buffers or does not point to a valid start
|
||||
of an allocation made in that allocator.
|
||||
- `Invalid_Argument`: Can occur if one of the arguments makes it impossible to
|
||||
satisfy a request (i.e. having alignment larger than the backing buffer
|
||||
of the allocation).
|
||||
- `Mode_Not_Implemented`: The allocator does not support the specified
|
||||
operation. For example, an arena does not support freeing individual
|
||||
allocations.
|
||||
*/
|
||||
Allocator_Error :: runtime.Allocator_Error
|
||||
|
||||
/*
|
||||
The allocator procedure.
|
||||
|
||||
This type represents allocation procedures. An allocation procedure is a single
|
||||
procedure, implementing all allocator functions such as allocating the memory,
|
||||
freeing the memory, etc.
|
||||
|
||||
Currently the type is defined as follows:
|
||||
|
||||
Allocator_Proc :: #type proc(
|
||||
allocator_data: rawptr,
|
||||
mode: Allocator_Mode,
|
||||
size: int,
|
||||
alignment: int,
|
||||
old_memory: rawptr,
|
||||
old_size: int,
|
||||
location: Source_Code_Location = #caller_location,
|
||||
) -> ([]byte, Allocator_Error);
|
||||
|
||||
The function of this procedure and the meaning of parameters depends on the
|
||||
value of the `mode` parameter.
|
||||
|
||||
## 1. `.Alloc`, `.Alloc_Non_Zeroed`
|
||||
|
||||
Allocates a memory region of size `size`, aligned on a boundary specified by
|
||||
`alignment`.
|
||||
|
||||
**Inputs**:
|
||||
- `allocator_data`: Pointer to the allocator data.
|
||||
- `mode`: `.Alloc` or `.Alloc_Non_Zeroed`.
|
||||
- `size`: The desired size of the memory region.
|
||||
- `alignment`: The desired alignmnet of the allocation.
|
||||
- `old_memory`: Unused, should be `nil`.
|
||||
- `old_size`: Unused, should be 0.
|
||||
|
||||
**Returns**:
|
||||
1. The memory region, if allocated successfully, or `nil` otherwise.
|
||||
2. An error, if allocation failed.
|
||||
|
||||
**Note**: Some allocators may return `nil`, even if no error is returned.
|
||||
Always check both the error and the allocated buffer.
|
||||
|
||||
Same as `.Alloc`.
|
||||
|
||||
## 2. `Free`
|
||||
|
||||
Frees a memory region located at the address specified by `old_memory`. If the
|
||||
allocator does not track sizes of allocations, the size should be specified in
|
||||
the `old_size` parameter.
|
||||
|
||||
**Inputs**:
|
||||
- `allocator_data`: Pointer to the allocator data.
|
||||
- `mode`: `.Free`.
|
||||
- `size`: Unused, should be 0.
|
||||
- `alignment`: Unused, should be 0.
|
||||
- `old_memory`: Pointer to the memory region to free.
|
||||
- `old_size`: The size of the memory region to free. This parameter is optional
|
||||
if the allocator keeps track of the sizes of allocations.
|
||||
|
||||
**Returns**:
|
||||
1. `nil`
|
||||
2. Error, if freeing failed.
|
||||
|
||||
## 3. `Free_All`
|
||||
|
||||
Frees all allocations, associated with the allocator, making it available for
|
||||
further allocations using the same backing buffers.
|
||||
|
||||
**Inputs**:
|
||||
- `allocator_data`: Pointer to the allocator data.
|
||||
- `mode`: `.Free_All`.
|
||||
- `size`: Unused, should be 0.
|
||||
- `alignment`: Unused, should be 0.
|
||||
- `old_memory`: Unused, should be `nil`.
|
||||
- `old_size`: Unused, should be `0`.
|
||||
|
||||
**Returns**:
|
||||
1. `nil`.
|
||||
2. Error, if freeing failed.
|
||||
|
||||
## 4. `Resize`, `Resize_Non_Zeroed`
|
||||
|
||||
Resizes the memory region, of the size `old_size` located at the address
|
||||
specified by `old_memory` to have the new size `size`. The slice of the new
|
||||
memory region is returned from the procedure. The allocator may attempt to
|
||||
keep the new memory region at the same address as the previous allocation,
|
||||
however no such guarantee is made. Do not assume the new memory region will
|
||||
be at the same address as the old memory region.
|
||||
|
||||
If `old_memory` pointer is `nil`, this function acts just like `.Alloc` or
|
||||
`.Alloc_Non_Zeroed`, using `size` and `alignment` to allocate a new memory
|
||||
region.
|
||||
|
||||
If `new_size` is `nil`, the procedure acts just like `.Free`, freeing the
|
||||
memory region `old_size` bytes in length, located at the address specified by
|
||||
`old_memory`.
|
||||
|
||||
**Inputs**:
|
||||
- `allocator_data`: Pointer to the allocator data.
|
||||
- `mode`: `.Resize` or `.Resize_All`.
|
||||
- `size`: The desired new size of the memory region.
|
||||
- `alignment`: The alignment of the new memory region, if its allocated
|
||||
- `old_memory`: The pointer to the memory region to resize.
|
||||
- `old_size`: The size of the memory region to resize. If the allocator
|
||||
keeps track of the sizes of allocations, this parameter is optional.
|
||||
|
||||
**Returns**:
|
||||
1. The slice of the memory region after resize operation, if successfull,
|
||||
`nil` otherwise.
|
||||
2. An error, if the resize failed.
|
||||
|
||||
**Note**: Some allocators may return `nil`, even if no error is returned.
|
||||
Always check both the error and the allocated buffer.
|
||||
*/
|
||||
Allocator_Proc :: runtime.Allocator_Proc
|
||||
/*
|
||||
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, location: Source_Code_Location = #caller_location) -> ([]byte, Allocator_Error);
|
||||
*/
|
||||
|
||||
/*
|
||||
Allocator.
|
||||
|
||||
This type represents generic interface for all allocators. Currently this type
|
||||
is defined as follows:
|
||||
|
||||
Allocator :: struct {
|
||||
procedure: Allocator_Proc,
|
||||
data: rawptr,
|
||||
}
|
||||
|
||||
- `procedure`: Pointer to the allocation procedure.
|
||||
- `data`: Pointer to the allocator data.
|
||||
*/
|
||||
Allocator :: runtime.Allocator
|
||||
/*
|
||||
Allocator :: struct {
|
||||
procedure: Allocator_Proc,
|
||||
data: rawptr,
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
Default alignment.
|
||||
|
||||
This value is the default alignment for all platforms that is used, if the
|
||||
alignment is not specified explicitly.
|
||||
*/
|
||||
DEFAULT_ALIGNMENT :: 2*align_of(rawptr)
|
||||
|
||||
/*
|
||||
Default page size.
|
||||
|
||||
This value is the default page size for the current platform.
|
||||
*/
|
||||
DEFAULT_PAGE_SIZE ::
|
||||
64 * 1024 when ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32 else
|
||||
16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else
|
||||
4 * 1024
|
||||
|
||||
/*
|
||||
Allocate memory.
|
||||
|
||||
This function allocates `size` bytes of memory, aligned to a boundary specified
|
||||
by `alignment` using the allocator specified by `allocator`.
|
||||
|
||||
**Inputs**:
|
||||
- `size`: The desired size of the allocated memory region.
|
||||
- `alignment`: The desired alignment of the allocated memory region.
|
||||
- `allocator`: The allocator to allocate from.
|
||||
|
||||
**Returns**:
|
||||
1. Pointer to the allocated memory, or `nil` if allocation failed.
|
||||
2. Error, if the allocation failed.
|
||||
*/
|
||||
@(require_results)
|
||||
alloc :: proc(
|
||||
size: int,
|
||||
@@ -73,6 +279,21 @@ alloc :: proc(
|
||||
return raw_data(data), err
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate memory.
|
||||
|
||||
This function allocates `size` bytes of memory, aligned to a boundary specified
|
||||
by `alignment` using the allocator specified by `allocator`.
|
||||
|
||||
**Inputs**:
|
||||
- `size`: The desired size of the allocated memory region.
|
||||
- `alignment`: The desired alignment of the allocated memory region.
|
||||
- `allocator`: The allocator to allocate from.
|
||||
|
||||
**Returns**:
|
||||
1. Slice of the allocated memory region, or `nil` if allocation failed.
|
||||
2. Error, if the allocation failed.
|
||||
*/
|
||||
@(require_results)
|
||||
alloc_bytes :: proc(
|
||||
size: int,
|
||||
@@ -83,6 +304,22 @@ alloc_bytes :: proc(
|
||||
return runtime.mem_alloc(size, alignment, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate non-zeroed memory.
|
||||
|
||||
This function allocates `size` bytes of memory, aligned to a boundary specified
|
||||
by `alignment` using the allocator specified by `allocator`. This procedure
|
||||
does not explicitly zero-initialize allocated memory region.
|
||||
|
||||
**Inputs**:
|
||||
- `size`: The desired size of the allocated memory region.
|
||||
- `alignment`: The desired alignment of the allocated memory region.
|
||||
- `allocator`: The allocator to allocate from.
|
||||
|
||||
**Returns**:
|
||||
1. Slice of the allocated memory region, or `nil` if allocation failed.
|
||||
2. Error, if the allocation failed.
|
||||
*/
|
||||
@(require_results)
|
||||
alloc_bytes_non_zeroed :: proc(
|
||||
size: int,
|
||||
@@ -93,6 +330,16 @@ alloc_bytes_non_zeroed :: proc(
|
||||
return runtime.mem_alloc_non_zeroed(size, alignment, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free memory.
|
||||
|
||||
This procedure frees memory region located at the address, specified by `ptr`,
|
||||
allocated from the allocator specified by `allocator`.
|
||||
|
||||
**Inputs**:
|
||||
- `ptr`: Pointer to the memory region to free.
|
||||
- `allocator`: The allocator to free to.
|
||||
*/
|
||||
free :: proc(
|
||||
ptr: rawptr,
|
||||
allocator := context.allocator,
|
||||
@@ -101,15 +348,42 @@ free :: proc(
|
||||
return runtime.mem_free(ptr, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a memory region.
|
||||
|
||||
This procedure frees `size` bytes of memory region located at the address,
|
||||
specified by `ptr`, allocated from the allocator specified by `allocator`.
|
||||
|
||||
**Inputs**:
|
||||
- `ptr`: Pointer to the memory region to free.
|
||||
- `size`: The size of the memory region to free.
|
||||
- `allocator`: The allocator to free to.
|
||||
|
||||
**Returns**:
|
||||
- The error, if freeing failed.
|
||||
*/
|
||||
free_with_size :: proc(
|
||||
ptr: rawptr,
|
||||
byte_count: int,
|
||||
size: int,
|
||||
allocator := context.allocator,
|
||||
loc := #caller_location,
|
||||
) -> Allocator_Error {
|
||||
return runtime.mem_free_with_size(ptr, byte_count, allocator, loc)
|
||||
return runtime.mem_free_with_size(ptr, size, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a memory region.
|
||||
|
||||
This procedure frees memory region, specified by `bytes`, allocated from the
|
||||
allocator specified by `allocator`.
|
||||
|
||||
**Inputs**:
|
||||
- `bytes`: The memory region to free.
|
||||
- `allocator`: The allocator to free to.
|
||||
|
||||
**Returns**:
|
||||
- The error, if freeing failed.
|
||||
*/
|
||||
free_bytes :: proc(
|
||||
bytes: []byte,
|
||||
allocator := context.allocator,
|
||||
@@ -118,10 +392,45 @@ free_bytes :: proc(
|
||||
return runtime.mem_free_bytes(bytes, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free all allocations.
|
||||
|
||||
This procedure frees all allocations made on the allocator specified by
|
||||
`allocator` to that allocator, making it available for further allocations.
|
||||
*/
|
||||
free_all :: proc(allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
return runtime.mem_free_all(allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Resize a memory region.
|
||||
|
||||
This procedure resizes a memory region, `old_size` bytes in size, located at
|
||||
the address specified by `ptr`, such that it has a new size, specified by
|
||||
`new_size` and and is aligned on a boundary specified by `alignment`.
|
||||
|
||||
If the `ptr` parameter is `nil`, `resize()` acts just like `alloc`, allocating
|
||||
`new_size` bytes, aligned on a boundary specified by `alignment`.
|
||||
|
||||
If the `new_size` parameter is `0`, `resize()` acts just like `free`, freeing
|
||||
the memory region `old_size` bytes in length, located at the address specified
|
||||
by `ptr`.
|
||||
|
||||
**Inputs**:
|
||||
- `ptr`: Pointer to the memory region to resize.
|
||||
- `old_size`: Size of the memory region to resize.
|
||||
- `new_size`: The desired size of the resized memory region.
|
||||
- `alignment`: The desired alignment of the resized memory region.
|
||||
- `allocator`: The owner of the memory region to resize.
|
||||
|
||||
**Returns**:
|
||||
1. The pointer to the resized memory region, if successfull, `nil` otherwise.
|
||||
2. Error, if resize failed.
|
||||
|
||||
**Note**: The `alignment` parameter is used to preserve the original alignment
|
||||
of the allocation, if `resize()` needs to relocate the memory region. Do not
|
||||
use `resize()` to change the alignment of the allocated memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
resize :: proc(
|
||||
ptr: rawptr,
|
||||
@@ -135,6 +444,33 @@ resize :: proc(
|
||||
return raw_data(data), err
|
||||
}
|
||||
|
||||
/*
|
||||
Resize a memory region.
|
||||
|
||||
This procedure resizes a memory region, specified by `old_data`, such that it
|
||||
has a new size, specified by `new_size` and and is aligned on a boundary
|
||||
specified by `alignment`.
|
||||
|
||||
If the `old_data` parameter is `nil`, `resize()` acts just like `alloc`,
|
||||
allocating `new_size` bytes, aligned on a boundary specified by `alignment`.
|
||||
|
||||
If the `new_size` parameter is `0`, `resize()` acts just like `free`, freeing
|
||||
the memory region specified by `old_data`.
|
||||
|
||||
**Inputs**:
|
||||
- `old_data`: Pointer to the memory region to resize.
|
||||
- `new_size`: The desired size of the resized memory region.
|
||||
- `alignment`: The desired alignment of the resized memory region.
|
||||
- `allocator`: The owner of the memory region to resize.
|
||||
|
||||
**Returns**:
|
||||
1. The resized memory region, if successfull, `nil` otherwise.
|
||||
2. Error, if resize failed.
|
||||
|
||||
**Note**: The `alignment` parameter is used to preserve the original alignment
|
||||
of the allocation, if `resize()` needs to relocate the memory region. Do not
|
||||
use `resize()` to change the alignment of the allocated memory region.
|
||||
*/
|
||||
@(require_results)
|
||||
resize_bytes :: proc(
|
||||
old_data: []byte,
|
||||
@@ -146,6 +482,9 @@ resize_bytes :: proc(
|
||||
return runtime.mem_resize(raw_data(old_data), len(old_data), new_size, alignment, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Query allocator features.
|
||||
*/
|
||||
@(require_results)
|
||||
query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) {
|
||||
if allocator.procedure != nil {
|
||||
@@ -155,6 +494,9 @@ query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: A
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
Query allocator information.
|
||||
*/
|
||||
@(require_results)
|
||||
query_info :: proc(
|
||||
pointer: rawptr,
|
||||
@@ -168,6 +510,9 @@ query_info :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Free a string.
|
||||
*/
|
||||
delete_string :: proc(
|
||||
str: string,
|
||||
allocator := context.allocator,
|
||||
@@ -176,6 +521,9 @@ delete_string :: proc(
|
||||
return runtime.delete_string(str, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a cstring.
|
||||
*/
|
||||
delete_cstring :: proc(
|
||||
str: cstring,
|
||||
allocator := context.allocator,
|
||||
@@ -184,6 +532,9 @@ delete_cstring :: proc(
|
||||
return runtime.delete_cstring(str, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a dynamic array.
|
||||
*/
|
||||
delete_dynamic_array :: proc(
|
||||
array: $T/[dynamic]$E,
|
||||
loc := #caller_location,
|
||||
@@ -191,6 +542,9 @@ delete_dynamic_array :: proc(
|
||||
return runtime.delete_dynamic_array(array, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a slice.
|
||||
*/
|
||||
delete_slice :: proc(
|
||||
array: $T/[]$E,
|
||||
allocator := context.allocator,
|
||||
@@ -199,6 +553,9 @@ delete_slice :: proc(
|
||||
return runtime.delete_slice(array, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free a map.
|
||||
*/
|
||||
delete_map :: proc(
|
||||
m: $T/map[$K]$V,
|
||||
loc := #caller_location,
|
||||
@@ -206,6 +563,9 @@ delete_map :: proc(
|
||||
return runtime.delete_map(m, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Free.
|
||||
*/
|
||||
delete :: proc{
|
||||
delete_string,
|
||||
delete_cstring,
|
||||
@@ -214,6 +574,13 @@ delete :: proc{
|
||||
delete_map,
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new object.
|
||||
|
||||
This procedure allocates a new object of type `T` using an allocator specified
|
||||
by `allocator`, and returns a pointer to the allocated object, if allocated
|
||||
successfully, or `nil` otherwise.
|
||||
*/
|
||||
@(require_results)
|
||||
new :: proc(
|
||||
$T: typeid,
|
||||
@@ -223,6 +590,14 @@ new :: proc(
|
||||
return new_aligned(T, align_of(T), allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new object with alignment.
|
||||
|
||||
This procedure allocates a new object of type `T` using an allocator specified
|
||||
by `allocator`, and returns a pointer, aligned on a boundary specified by
|
||||
`alignment` to the allocated object, if allocated successfully, or `nil`
|
||||
otherwise.
|
||||
*/
|
||||
@(require_results)
|
||||
new_aligned :: proc(
|
||||
$T: typeid,
|
||||
@@ -233,6 +608,14 @@ new_aligned :: proc(
|
||||
return runtime.new_aligned(T, alignment, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new object and initialize it with a value.
|
||||
|
||||
This procedure allocates a new object of type `T` using an allocator specified
|
||||
by `allocator`, and returns a pointer, aligned on a boundary specified by
|
||||
`alignment` to the allocated object, if allocated successfully, or `nil`
|
||||
otherwise. The allocated object is initialized with `data`.
|
||||
*/
|
||||
@(require_results)
|
||||
new_clone :: proc(
|
||||
data: $T,
|
||||
@@ -242,6 +625,13 @@ new_clone :: proc(
|
||||
return runtime.new_clone(data, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new slice with alignment.
|
||||
|
||||
This procedure allocates a new slice of type `T` with length `len`, aligned
|
||||
on a boundary specified by `alignment` from an allocator specified by
|
||||
`allocator`, and returns the allocated slice.
|
||||
*/
|
||||
@(require_results)
|
||||
make_aligned :: proc(
|
||||
$T: typeid/[]$E,
|
||||
@@ -253,6 +643,12 @@ make_aligned :: proc(
|
||||
return runtime.make_aligned(T, len, alignment, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new slice.
|
||||
|
||||
This procedure allocates a new slice of type `T` with length `len`, from an
|
||||
allocator specified by `allocator`, and returns the allocated slice.
|
||||
*/
|
||||
@(require_results)
|
||||
make_slice :: proc(
|
||||
$T: typeid/[]$E,
|
||||
@@ -263,6 +659,12 @@ make_slice :: proc(
|
||||
return runtime.make_slice(T, len, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a dynamic array.
|
||||
|
||||
This procedure creates a dynamic array of type `T`, with `allocator` as its
|
||||
backing allocator, and initial length and capacity of `0`.
|
||||
*/
|
||||
@(require_results)
|
||||
make_dynamic_array :: proc(
|
||||
$T: typeid/[dynamic]$E,
|
||||
@@ -272,6 +674,13 @@ make_dynamic_array :: proc(
|
||||
return runtime.make_dynamic_array(T, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a dynamic array with initial length.
|
||||
|
||||
This procedure creates a dynamic array of type `T`, with `allocator` as its
|
||||
backing allocator, and initial capacity of `0`, and initial length specified by
|
||||
`len`.
|
||||
*/
|
||||
@(require_results)
|
||||
make_dynamic_array_len :: proc(
|
||||
$T: typeid/[dynamic]$E,
|
||||
@@ -282,6 +691,13 @@ make_dynamic_array_len :: proc(
|
||||
return runtime.make_dynamic_array_len_cap(T, len, len, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a dynamic array with initial length and capacity.
|
||||
|
||||
This procedure creates a dynamic array of type `T`, with `allocator` as its
|
||||
backing allocator, and initial capacity specified by `cap`, and initial length
|
||||
specified by `len`.
|
||||
*/
|
||||
@(require_results)
|
||||
make_dynamic_array_len_cap :: proc(
|
||||
$T: typeid/[dynamic]$E,
|
||||
@@ -293,6 +709,13 @@ make_dynamic_array_len_cap :: proc(
|
||||
return runtime.make_dynamic_array_len_cap(T, len, cap, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a map.
|
||||
|
||||
This procedure creates a map of type `T` with initial capacity specified by
|
||||
`cap`, that is using an allocator specified by `allocator` as its backing
|
||||
allocator.
|
||||
*/
|
||||
@(require_results)
|
||||
make_map :: proc(
|
||||
$T: typeid/map[$K]$E,
|
||||
@@ -303,6 +726,12 @@ make_map :: proc(
|
||||
return runtime.make_map(T, cap, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a multi pointer.
|
||||
|
||||
This procedure allocates a multipointer of type `T` pointing to `len` elements,
|
||||
from an allocator specified by `allocator`.
|
||||
*/
|
||||
@(require_results)
|
||||
make_multi_pointer :: proc(
|
||||
$T: typeid/[^]$E,
|
||||
@@ -313,6 +742,9 @@ make_multi_pointer :: proc(
|
||||
return runtime.make_multi_pointer(T, len, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate.
|
||||
*/
|
||||
make :: proc{
|
||||
make_slice,
|
||||
make_dynamic_array,
|
||||
@@ -322,6 +754,23 @@ make :: proc{
|
||||
make_multi_pointer,
|
||||
}
|
||||
|
||||
/*
|
||||
Default resize procedure.
|
||||
|
||||
When allocator does not support resize operation, but supports `.Alloc` and
|
||||
`.Free`, this procedure is used to implement allocator's default behavior on
|
||||
resize.
|
||||
|
||||
The behavior of the function is as follows:
|
||||
|
||||
- If `new_size` is `0`, the function acts like `free()`, freeing the memory
|
||||
region of `old_size` bytes located at `old_memory`.
|
||||
- If `old_memory` is `nil`, the function acts like `alloc()`, allocating
|
||||
`new_size` bytes of memory aligned on a boundary specified by `alignment`.
|
||||
- Otherwise, a new memory region of size `new_size` is allocated, then the
|
||||
data from the old memory region is copied and the old memory region is
|
||||
freed.
|
||||
*/
|
||||
@(require_results)
|
||||
default_resize_align :: proc(
|
||||
old_memory: rawptr,
|
||||
@@ -343,6 +792,27 @@ default_resize_align :: proc(
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
Default resize procedure.
|
||||
|
||||
When allocator does not support resize operation, but supports
|
||||
`.Alloc_Non_Zeroed` and `.Free`, this procedure is used to implement allocator's
|
||||
default behavior on
|
||||
resize.
|
||||
|
||||
Unlike `default_resize_align` no new memory is being explicitly
|
||||
zero-initialized.
|
||||
|
||||
The behavior of the function is as follows:
|
||||
|
||||
- If `new_size` is `0`, the function acts like `free()`, freeing the memory
|
||||
region of `old_size` bytes located at `old_memory`.
|
||||
- If `old_memory` is `nil`, the function acts like `alloc()`, allocating
|
||||
`new_size` bytes of memory aligned on a boundary specified by `alignment`.
|
||||
- Otherwise, a new memory region of size `new_size` is allocated, then the
|
||||
data from the old memory region is copied and the old memory region is
|
||||
freed.
|
||||
*/
|
||||
@(require_results)
|
||||
default_resize_bytes_align_non_zeroed :: proc(
|
||||
old_data: []byte,
|
||||
@@ -354,6 +824,23 @@ default_resize_bytes_align_non_zeroed :: proc(
|
||||
return _default_resize_bytes_align(old_data, new_size, alignment, false, allocator, loc)
|
||||
}
|
||||
|
||||
/*
|
||||
Default resize procedure.
|
||||
|
||||
When allocator does not support resize operation, but supports `.Alloc` and
|
||||
`.Free`, this procedure is used to implement allocator's default behavior on
|
||||
resize.
|
||||
|
||||
The behavior of the function is as follows:
|
||||
|
||||
- If `new_size` is `0`, the function acts like `free()`, freeing the memory
|
||||
region specified by `old_data`.
|
||||
- If `old_data` is `nil`, the function acts like `alloc()`, allocating
|
||||
`new_size` bytes of memory aligned on a boundary specified by `alignment`.
|
||||
- Otherwise, a new memory region of size `new_size` is allocated, then the
|
||||
data from the old memory region is copied and the old memory region is
|
||||
freed.
|
||||
*/
|
||||
@(require_results)
|
||||
default_resize_bytes_align :: proc(
|
||||
old_data: []byte,
|
||||
@@ -383,16 +870,13 @@ _default_resize_bytes_align :: #force_inline proc(
|
||||
return alloc_bytes_non_zeroed(new_size, alignment, allocator, loc)
|
||||
}
|
||||
}
|
||||
|
||||
if new_size == 0 {
|
||||
err := free_bytes(old_data, allocator, loc)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if new_size == old_size {
|
||||
return old_data, .None
|
||||
}
|
||||
|
||||
new_memory : []byte
|
||||
err : Allocator_Error
|
||||
if should_zero {
|
||||
@@ -403,7 +887,6 @@ _default_resize_bytes_align :: #force_inline proc(
|
||||
if new_memory == nil || err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
runtime.copy(new_memory, old_data)
|
||||
free_bytes(old_data, allocator, loc)
|
||||
return new_memory, err
|
||||
|
||||
Reference in New Issue
Block a user