Selaa lähdekoodia

[mem]: Add alloc_non_zeroed variant to dynamic pool

flysand7 1 vuosi sitten
vanhempi
commit
03f6b9bbf6
1 muutettua tiedostoa jossa 122 lisäystä ja 123 poistoa
  1. 122 123
      core/mem/allocators.odin

+ 122 - 123
core/mem/allocators.odin

@@ -795,93 +795,35 @@ DYNAMIC_POOL_OUT_OF_BAND_SIZE_DEFAULT :: DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT
 dynamic_pool_allocator_proc :: dynamic_arena_allocator_proc
 dynamic_pool_allocator_proc :: dynamic_arena_allocator_proc
 dynamic_pool_free_all :: dynamic_arena_free_all
 dynamic_pool_free_all :: dynamic_arena_free_all
 dynamic_pool_reset :: dynamic_arena_reset
 dynamic_pool_reset :: dynamic_arena_reset
-dynamic_pool_alloc_bytes :: dynamic_arena_alloc_bytes
-dynamic_pool_alloc :: dynamic_arena_alloc
+dynamic_pool_alloc_bytes :: dynamic_arena_alloc
+dynamic_pool_alloc :: _dynamic_arena_alloc_ptr
 dynamic_pool_init :: dynamic_arena_init
 dynamic_pool_init :: dynamic_arena_init
 dynamic_pool_allocator :: dynamic_arena_allocator
 dynamic_pool_allocator :: dynamic_arena_allocator
+dynamic_pool_destroy :: dynamic_arena_destroy
+
+DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT :: 65536
+DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT :: 6554
 
 
 Dynamic_Arena :: struct {
 Dynamic_Arena :: struct {
-	block_size:    int,
+	block_size: int,
 	out_band_size: int,
 	out_band_size: int,
-	alignment:     int,
-
-	unused_blocks:        [dynamic]rawptr,
-	used_blocks:          [dynamic]rawptr,
+	alignment: int,
+	unused_blocks: [dynamic]rawptr,
+	used_blocks: [dynamic]rawptr,
 	out_band_allocations: [dynamic]rawptr,
 	out_band_allocations: [dynamic]rawptr,
-
 	current_block: rawptr,
 	current_block: rawptr,
-	current_pos:   rawptr,
-	bytes_left:    int,
-
+	current_pos: rawptr,
+	bytes_left: int,
 	block_allocator: Allocator,
 	block_allocator: Allocator,
 }
 }
 
 
-DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT :: 65536
-DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT :: 6554
-
-dynamic_arena_allocator_proc :: proc(
-	allocator_data: rawptr,
-	mode: Allocator_Mode,
-	size: int,
-	alignment: int,
-	old_memory: rawptr,
-	old_size: int,
-	loc := #caller_location,
-) -> ([]byte, Allocator_Error) {
-	pool := (^Dynamic_Arena)(allocator_data)
-
-	switch mode {
-	case .Alloc, .Alloc_Non_Zeroed:
-		return dynamic_arena_alloc_bytes(pool, size)
-	case .Free:
-		return nil, .Mode_Not_Implemented
-	case .Free_All:
-		dynamic_arena_free_all(pool)
-		return nil, nil
-	case .Resize, .Resize_Non_Zeroed:
-		if old_size >= size {
-			return byte_slice(old_memory, size), nil
-		}
-		data, err := dynamic_arena_alloc_bytes(pool, size)
-		if err == nil {
-			runtime.copy(data, byte_slice(old_memory, old_size))
-		}
-		return data, err
-
-	case .Query_Features:
-		set := (^Allocator_Mode_Set)(old_memory)
-		if set != nil {
-			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features, .Query_Info}
-		}
-		return nil, nil
-
-	case .Query_Info:
-		info := (^Allocator_Query_Info)(old_memory)
-		if info != nil && info.pointer != nil {
-			info.size = pool.block_size
-			info.alignment = pool.alignment
-			return byte_slice(info, size_of(info^)), nil
-		}
-		return nil, nil
-	}
-	return nil, nil
-}
-
-@(require_results)
-dynamic_arena_allocator :: proc(pool: ^Dynamic_Arena) -> Allocator {
-	return Allocator{
-		procedure = dynamic_arena_allocator_proc,
-		data = pool,
-	}
-}
-
 dynamic_arena_init :: proc(
 dynamic_arena_init :: proc(
 	pool: ^Dynamic_Arena,
 	pool: ^Dynamic_Arena,
 	block_allocator := context.allocator,
 	block_allocator := context.allocator,
 	array_allocator := context.allocator,
 	array_allocator := context.allocator,
 	block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT,
 	block_size := DYNAMIC_ARENA_BLOCK_SIZE_DEFAULT,
 	out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT,
 	out_band_size := DYNAMIC_ARENA_OUT_OF_BAND_SIZE_DEFAULT,
-	alignment := 8,
+	alignment := DEFAULT_ALIGNMENT,
 ) {
 ) {
 	pool.block_size = block_size
 	pool.block_size = block_size
 	pool.out_band_size = out_band_size
 	pool.out_band_size = out_band_size
@@ -892,6 +834,14 @@ dynamic_arena_init :: proc(
 	pool.used_blocks.allocator = array_allocator
 	pool.used_blocks.allocator = array_allocator
 }
 }
 
 
+@(require_results)
+dynamic_arena_allocator :: proc(pool: ^Dynamic_Arena) -> Allocator {
+	return Allocator{
+		procedure = dynamic_arena_allocator_proc,
+		data = pool,
+	}
+}
+
 dynamic_arena_destroy :: proc(pool: ^Dynamic_Arena) {
 dynamic_arena_destroy :: proc(pool: ^Dynamic_Arena) {
 	dynamic_arena_free_all(pool)
 	dynamic_arena_free_all(pool)
 	delete(pool.unused_blocks)
 	delete(pool.unused_blocks)
@@ -900,62 +850,66 @@ dynamic_arena_destroy :: proc(pool: ^Dynamic_Arena) {
 	zero(pool, size_of(pool^))
 	zero(pool, size_of(pool^))
 }
 }
 
 
-@(require_results)
-dynamic_arena_alloc :: proc(pool: ^Dynamic_Arena, bytes: int) -> (rawptr, Allocator_Error) {
-	data, err := dynamic_arena_alloc_bytes(pool, bytes)
+@(private="file")
+_dynamic_arena_cycle_new_block :: proc(p: ^Dynamic_Arena, loc := #caller_location) -> (err: Allocator_Error) {
+	if p.block_allocator.procedure == nil {
+		panic("You must call pool_init on a Pool before using it", loc)
+	}
+	if p.current_block != nil {
+		append(&p.used_blocks, p.current_block, loc=loc)
+	}
+	new_block: rawptr
+	if len(p.unused_blocks) > 0 {
+		new_block = pop(&p.unused_blocks)
+	} else {
+		data: []byte
+		data, err = p.block_allocator.procedure(
+			p.block_allocator.data,
+			Allocator_Mode.Alloc,
+			p.block_size,
+			p.alignment,
+			nil,
+			0,
+		)
+		new_block = raw_data(data)
+	}
+	p.bytes_left    = p.block_size
+	p.current_pos   = new_block
+	p.current_block = new_block
+	return
+}
+
+@(private, require_results)
+_dynamic_arena_alloc_ptr :: proc(pool: ^Dynamic_Arena, size: int, loc := #caller_location) -> (rawptr, Allocator_Error) {
+	data, err := dynamic_arena_alloc(pool, size, loc)
 	return raw_data(data), err
 	return raw_data(data), err
 }
 }
 
 
 @(require_results)
 @(require_results)
-dynamic_arena_alloc_bytes :: proc(p: ^Dynamic_Arena, bytes: int) -> ([]byte, Allocator_Error) {
-	cycle_new_block :: proc(p: ^Dynamic_Arena) -> (err: Allocator_Error) {
-		if p.block_allocator.procedure == nil {
-			panic("You must call pool_init on a Pool before using it")
-		}
-
-		if p.current_block != nil {
-			append(&p.used_blocks, p.current_block)
-		}
-
-		new_block: rawptr
-		if len(p.unused_blocks) > 0 {
-			new_block = pop(&p.unused_blocks)
-		} else {
-			data: []byte
-			data, err = p.block_allocator.procedure(
-				p.block_allocator.data,
-				Allocator_Mode.Alloc,
-				p.block_size,
-				p.alignment,
-				nil,
-				0,
-			)
-			new_block = raw_data(data)
-		}
-
-		p.bytes_left    = p.block_size
-		p.current_pos   = new_block
-		p.current_block = new_block
-		return
+dynamic_arena_alloc :: proc(p: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
+	bytes, err := dynamic_arena_alloc_non_zeroed(p, size, loc)
+	if bytes != nil {
+		zero_slice(bytes)
 	}
 	}
+	return bytes, err
+}
 
 
-	n := align_formula(bytes, p.alignment)
+@(require_results)
+dynamic_arena_alloc_non_zeroed :: proc(p: ^Dynamic_Arena, size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
+	n := align_formula(size, p.alignment)
 	if n > p.block_size {
 	if n > p.block_size {
 		return nil, .Invalid_Argument
 		return nil, .Invalid_Argument
 	}
 	}
 	if n >= p.out_band_size {
 	if n >= p.out_band_size {
-		assert(p.block_allocator.procedure != nil)
-		memory, err := p.block_allocator.procedure(p.block_allocator.data, Allocator_Mode.Alloc,
-		                                           p.block_size, p.alignment,
-		                                           nil, 0)
+		assert(p.block_allocator.procedure != nil, "Backing block allocator must be initialized", loc=loc)
+		memory, err := alloc_bytes_non_zeroed(p.block_size, p.alignment, p.block_allocator, loc)
 		if memory != nil {
 		if memory != nil {
-			append(&p.out_band_allocations, raw_data(memory))
+			append(&p.out_band_allocations, raw_data(memory), loc = loc)
 		}
 		}
 		return memory, err
 		return memory, err
 	}
 	}
-
 	if p.bytes_left < n {
 	if p.bytes_left < n {
-		err := cycle_new_block(p)
+		err := _dynamic_arena_cycle_new_block(p, loc)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -963,41 +917,86 @@ dynamic_arena_alloc_bytes :: proc(p: ^Dynamic_Arena, bytes: int) -> ([]byte, All
 			return nil, .Out_Of_Memory
 			return nil, .Out_Of_Memory
 		}
 		}
 	}
 	}
-
 	memory := p.current_pos
 	memory := p.current_pos
 	p.current_pos = ([^]byte)(p.current_pos)[n:]
 	p.current_pos = ([^]byte)(p.current_pos)[n:]
 	p.bytes_left -= n
 	p.bytes_left -= n
-	return ([^]byte)(memory)[:bytes], nil
+	return ([^]byte)(memory)[:size], nil
 }
 }
 
 
-dynamic_arena_reset :: proc(p: ^Dynamic_Arena) {
+dynamic_arena_reset :: proc(p: ^Dynamic_Arena, loc := #caller_location) {
 	if p.current_block != nil {
 	if p.current_block != nil {
-		append(&p.unused_blocks, p.current_block)
+		append(&p.unused_blocks, p.current_block, loc=loc)
 		p.current_block = nil
 		p.current_block = nil
 	}
 	}
-
 	for block in p.used_blocks {
 	for block in p.used_blocks {
-		append(&p.unused_blocks, block)
+		append(&p.unused_blocks, block, loc=loc)
 	}
 	}
 	clear(&p.used_blocks)
 	clear(&p.used_blocks)
-
 	for a in p.out_band_allocations {
 	for a in p.out_band_allocations {
-		free(a, p.block_allocator)
+		free(a, p.block_allocator, loc=loc)
 	}
 	}
 	clear(&p.out_band_allocations)
 	clear(&p.out_band_allocations)
-
-	p.bytes_left = 0 // Make new allocations call `cycle_new_block` again.
+	p.bytes_left = 0 // Make new allocations call `_dynamic_arena_cycle_new_block` again.
 }
 }
 
 
 dynamic_arena_free_all :: proc(p: ^Dynamic_Arena) {
 dynamic_arena_free_all :: proc(p: ^Dynamic_Arena) {
 	dynamic_arena_reset(p)
 	dynamic_arena_reset(p)
-
 	for block in p.unused_blocks {
 	for block in p.unused_blocks {
 		free(block, p.block_allocator)
 		free(block, p.block_allocator)
 	}
 	}
 	clear(&p.unused_blocks)
 	clear(&p.unused_blocks)
 }
 }
 
 
+dynamic_arena_allocator_proc :: proc(
+	allocator_data: rawptr,
+	mode: Allocator_Mode,
+	size: int,
+	alignment: int,
+	old_memory: rawptr,
+	old_size: int,
+	loc := #caller_location,
+) -> ([]byte, Allocator_Error) {
+	pool := (^Dynamic_Arena)(allocator_data)
+
+	switch mode {
+	case .Alloc:
+		return dynamic_arena_alloc(pool, size, loc)
+	case .Alloc_Non_Zeroed:
+		return dynamic_arena_alloc_non_zeroed(pool, size, loc)
+	case .Free:
+		return nil, .Mode_Not_Implemented
+	case .Free_All:
+		dynamic_arena_free_all(pool)
+		return nil, nil
+	case .Resize, .Resize_Non_Zeroed:
+		if old_size >= size {
+			return byte_slice(old_memory, size), nil
+		}
+		data, err := dynamic_arena_alloc(pool, size)
+		if err == nil {
+			runtime.copy(data, byte_slice(old_memory, old_size))
+		}
+		return data, err
+
+	case .Query_Features:
+		set := (^Allocator_Mode_Set)(old_memory)
+		if set != nil {
+			set^ = {.Alloc, .Alloc_Non_Zeroed, .Free_All, .Resize, .Resize_Non_Zeroed, .Query_Features, .Query_Info}
+		}
+		return nil, nil
+
+	case .Query_Info:
+		info := (^Allocator_Query_Info)(old_memory)
+		if info != nil && info.pointer != nil {
+			info.size = pool.block_size
+			info.alignment = pool.alignment
+			return byte_slice(info, size_of(info^)), nil
+		}
+		return nil, nil
+	}
+	return nil, nil
+}
+
 
 
 
 
 panic_allocator_proc :: proc(
 panic_allocator_proc :: proc(