mirror of
https://github.com/odin-lang/Odin.git
synced 2026-06-06 10:44:06 +00:00
Add mutex to virtual.Arena; add virtual.arena_temp_ignore
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:mem"
|
||||
import "core:sync"
|
||||
|
||||
Arena_Kind :: enum uint {
|
||||
Growing = 0, // Chained memory blocks (singly linked list).
|
||||
@@ -15,6 +16,7 @@ Arena :: struct {
|
||||
total_reserved: uint,
|
||||
minimum_block_size: uint,
|
||||
temp_count: uint,
|
||||
mutex: sync.Mutex,
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +80,8 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
|
||||
switch arena.kind {
|
||||
case .Growing:
|
||||
if arena.curr_block == nil || (safe_add(arena.curr_block.used, size) or_else 0) > arena.curr_block.reserved {
|
||||
@@ -116,6 +120,8 @@ arena_alloc :: proc(arena: ^Arena, size: uint, alignment: uint, loc := #caller_l
|
||||
}
|
||||
|
||||
arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location) -> bool {
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
|
||||
if arena.curr_block != nil {
|
||||
assert(arena.kind != .Growing, "expected a non .Growing arena", loc)
|
||||
|
||||
@@ -135,6 +141,7 @@ arena_static_reset_to :: proc(arena: ^Arena, pos: uint, loc := #caller_location)
|
||||
}
|
||||
|
||||
arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_location) {
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
if free_block := arena.curr_block; free_block != nil {
|
||||
assert(arena.kind == .Growing, "expected a .Growing arena", loc)
|
||||
arena.curr_block = free_block.prev
|
||||
@@ -145,6 +152,7 @@ arena_growing_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_locat
|
||||
arena_free_all :: proc(arena: ^Arena) {
|
||||
switch arena.kind {
|
||||
case .Growing:
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
for arena.curr_block != nil {
|
||||
arena_growing_free_last_memory_block(arena)
|
||||
}
|
||||
@@ -287,6 +295,8 @@ Arena_Temp :: struct {
|
||||
@(require_results)
|
||||
arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) {
|
||||
assert(arena != nil, "nil arena", loc)
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
|
||||
temp.arena = arena
|
||||
temp.block = arena.curr_block
|
||||
if arena.curr_block != nil {
|
||||
@@ -299,6 +309,7 @@ arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena
|
||||
arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
|
||||
assert(temp.arena != nil, "nil arena", loc)
|
||||
arena := temp.arena
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
|
||||
memory_block_found := false
|
||||
for block := arena.curr_block; block != nil; block = block.prev {
|
||||
@@ -326,6 +337,16 @@ arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {
|
||||
arena.temp_count -= 1
|
||||
}
|
||||
|
||||
// Ignore the use of a `arena_temp_begin` entirely
|
||||
arena_temp_ignore :: proc(temp: Arena_Temp, loc := #caller_location) {
|
||||
assert(temp.arena != nil, "nil arena", loc)
|
||||
arena := temp.arena
|
||||
sync.mutex_guard(&arena.mutex)
|
||||
|
||||
assert(arena.temp_count > 0, "double-use of arena_temp_end", loc)
|
||||
arena.temp_count -= 1
|
||||
}
|
||||
|
||||
arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) {
|
||||
assert(arena.temp_count == 0, "Arena_Temp not been ended", loc)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ DEFAULT_PAGE_SIZE := uint(4096)
|
||||
|
||||
Allocator_Error :: mem.Allocator_Error
|
||||
|
||||
@(require_results)
|
||||
reserve :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
return _reserve(size)
|
||||
}
|
||||
@@ -15,6 +16,7 @@ commit :: proc "contextless" (data: rawptr, size: uint) -> Allocator_Error {
|
||||
return _commit(data, size)
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
reserve_and_commit :: proc "contextless" (size: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
data = reserve(size) or_return
|
||||
commit(raw_data(data), size) or_return
|
||||
@@ -57,6 +59,7 @@ Memory_Block_Flag :: enum u32 {
|
||||
Memory_Block_Flags :: distinct bit_set[Memory_Block_Flag; u32]
|
||||
|
||||
|
||||
@(require_results)
|
||||
memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags) -> (block: ^Memory_Block, err: Allocator_Error) {
|
||||
align_formula :: proc "contextless" (size, align: uint) -> uint {
|
||||
result := size + align-1
|
||||
@@ -100,6 +103,7 @@ memory_block_alloc :: proc(committed, reserved: uint, flags: Memory_Block_Flags)
|
||||
return &pmblock.block, nil
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []byte, err: Allocator_Error) {
|
||||
calc_alignment_offset :: proc "contextless" (block: ^Memory_Block, alignment: uintptr) -> uint {
|
||||
alignment_offset := uint(0)
|
||||
@@ -160,7 +164,7 @@ memory_block_dealloc :: proc(block_to_free: ^Memory_Block) {
|
||||
|
||||
|
||||
|
||||
@(private)
|
||||
@(private, require_results)
|
||||
safe_add :: #force_inline proc "contextless" (x, y: uint) -> (uint, bool) {
|
||||
z, did_overflow := intrinsics.overflow_add(x, y)
|
||||
return z, !did_overflow
|
||||
|
||||
Reference in New Issue
Block a user