Trying to figure out this bug with pools...
This commit is contained in:
parent
fb1a6063a7
commit
714d60ee34
@ -165,6 +165,10 @@ released :: proc {
|
||||
btn_released,
|
||||
}
|
||||
|
||||
sub :: proc {
|
||||
sub_range2,
|
||||
}
|
||||
|
||||
to_rl_rect :: proc {
|
||||
range2_to_rl_rect,
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ array_init_reserve :: proc
|
||||
|
||||
raw_mem : rawptr
|
||||
raw_mem, alloc_error = alloc( array_size, allocator = allocator )
|
||||
log( str_fmt_tmp("array reserved: %d", header_size + int(capacity) * size_of(Type) ))
|
||||
// log( str_fmt_tmp("array reserved: %d", header_size + int(capacity) * size_of(Type) ))
|
||||
if alloc_error != AllocatorError.None do return
|
||||
|
||||
result.header = cast( ^ArrayHeader(Type)) raw_mem;
|
||||
|
@ -13,6 +13,8 @@ The pool doesn't allocate any buckets on initialization unless the user specifes
|
||||
*/
|
||||
package sectr
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:mem"
|
||||
import "core:slice"
|
||||
|
||||
@ -29,13 +31,13 @@ PoolHeader :: struct {
|
||||
|
||||
free_list_head : ^Pool_FreeBlock,
|
||||
current_bucket : ^PoolBucket,
|
||||
bucket_list : DLL_NodeFL( PoolBucket)
|
||||
bucket_list : DLL_NodeFL( PoolBucket),
|
||||
}
|
||||
|
||||
PoolBucket :: struct {
|
||||
using nodes : DLL_NodePN( PoolBucket),
|
||||
next_block : uint,
|
||||
blocks : [^]byte
|
||||
blocks : [^]byte,
|
||||
}
|
||||
|
||||
Pool_FreeBlock :: struct {
|
||||
@ -88,21 +90,23 @@ pool_destroy :: proc ( using self : Pool )
|
||||
free( self.header, backing )
|
||||
}
|
||||
|
||||
pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> AllocatorError
|
||||
pool_allocate_buckets :: proc( pool : Pool, num_buckets : uint ) -> AllocatorError
|
||||
{
|
||||
profile(#procedure)
|
||||
pool := self
|
||||
if num_buckets == 0 {
|
||||
return .Invalid_Argument
|
||||
}
|
||||
header_size := cast(uint) align_forward_int( size_of(PoolBucket), int(alignment))
|
||||
bucket_size := header_size + bucket_capacity
|
||||
header_size := cast(uint) align_forward_int( size_of(PoolBucket), int(pool.alignment))
|
||||
bucket_size := header_size + pool.bucket_capacity
|
||||
to_allocate := cast(int) (bucket_size * num_buckets)
|
||||
|
||||
bucket_memory, alloc_error := alloc_bytes_non_zeroed( to_allocate, int(alignment), backing )
|
||||
pool_validate( pool )
|
||||
bucket_memory, alloc_error := alloc_bytes_non_zeroed( to_allocate, int(pool.alignment), pool.backing )
|
||||
pool_validate( pool )
|
||||
if alloc_error != .None {
|
||||
return alloc_error
|
||||
}
|
||||
verify( bucket_memory != nil, "Bucket memory is null")
|
||||
|
||||
next_bucket_ptr := cast( [^]byte) raw_data(bucket_memory)
|
||||
for index in 0 ..< num_buckets
|
||||
@ -110,15 +114,22 @@ pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> Alloca
|
||||
bucket := cast( ^PoolBucket) next_bucket_ptr
|
||||
bucket.blocks = memory_after_header(bucket)
|
||||
bucket.next_block = 0
|
||||
log( str_fmt_tmp("Pool (%d) allocated bucket: %p capacity: %d", self.block_size, raw_data(bucket_memory), bucket_capacity / self.block_size))
|
||||
log( str_fmt_tmp("Pool (%d) allocated bucket: %p capacity: %d",
|
||||
pool.block_size,
|
||||
raw_data(bucket_memory),
|
||||
pool.bucket_capacity / pool.block_size
|
||||
))
|
||||
|
||||
if bucket == cast(rawptr) uintptr(0x100017740D0) {
|
||||
runtime.debug_trap()
|
||||
}
|
||||
|
||||
if self.bucket_list.first == nil {
|
||||
self.bucket_list.first = bucket
|
||||
self.bucket_list.last = bucket
|
||||
if pool.bucket_list.first == nil {
|
||||
pool.bucket_list.first = bucket
|
||||
pool.bucket_list.last = bucket
|
||||
}
|
||||
else {
|
||||
dll_push_back( & self.bucket_list.last, bucket )
|
||||
dll_push_back( & pool.bucket_list.last, bucket )
|
||||
}
|
||||
// log( str_fmt_tmp("Bucket List First: %p", self.bucket_list.first))
|
||||
|
||||
@ -130,6 +141,10 @@ pool_allocate_buckets :: proc( using self : Pool, num_buckets : uint ) -> Alloca
|
||||
pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, alloc_error : AllocatorError )
|
||||
{
|
||||
pool := pool
|
||||
if pool.current_bucket != nil {
|
||||
verify( pool.current_bucket.blocks != nil, str_fmt_tmp("current_bucket was wiped %p", pool.current_bucket) )
|
||||
}
|
||||
|
||||
// profile(#procedure)
|
||||
alloc_error = .None
|
||||
|
||||
@ -150,6 +165,7 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
|
||||
if zero_memory {
|
||||
slice.zero(block)
|
||||
}
|
||||
verify(false, "WE SHOULD NEVER BE HERE")
|
||||
return
|
||||
}
|
||||
|
||||
@ -172,8 +188,8 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
|
||||
next := uintptr(pool.current_bucket.blocks) + uintptr(pool.current_bucket.next_block)
|
||||
end := uintptr(pool.current_bucket.blocks) + uintptr(pool.bucket_capacity)
|
||||
|
||||
blocks_left := end - next
|
||||
if blocks_left == 0
|
||||
blocks_left, overflow_signal := intrinsics.overflow_sub( end, next )
|
||||
if blocks_left == 0 || overflow_signal
|
||||
{
|
||||
// Compiler Bug
|
||||
// if current_bucket.next != nil {
|
||||
@ -181,6 +197,7 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
|
||||
// current_bucket = current_bucket.next
|
||||
// log( str_fmt_tmp("Bucket %p exhausted using %p", pool.current_bucket, pool.current_bucket.next))
|
||||
pool.current_bucket = pool.current_bucket.next
|
||||
verify( pool.current_bucket.blocks != nil, "Next's blocks are null?" )
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -191,9 +208,12 @@ pool_grab :: proc( pool : Pool, zero_memory := false ) -> ( block : []byte, allo
|
||||
return
|
||||
}
|
||||
pool.current_bucket = pool.current_bucket.next
|
||||
verify( pool.current_bucket.blocks != nil, "Next's blocks are null (Post new bucket alloc)?" )
|
||||
}
|
||||
}
|
||||
|
||||
verify( pool.current_bucket != nil, "Attempted to grab a block from a null bucket reference" )
|
||||
|
||||
// Compiler Bug
|
||||
// block = slice_ptr( current_bucket.blocks[ current_bucket.next_block:], int(block_size) )
|
||||
// self.current_bucket.next_block += block_size
|
||||
@ -246,6 +266,18 @@ pool_reset :: proc( using pool : Pool )
|
||||
pool.current_bucket = bucket_list.first
|
||||
}
|
||||
|
||||
pool_validate :: proc( pool : Pool )
|
||||
{
|
||||
pool := pool
|
||||
// Make sure all buckets don't show any indication of corruption
|
||||
bucket : ^PoolBucket = pool.bucket_list.first
|
||||
// Compiler bug ^^ same as pool_reset
|
||||
for ; bucket != nil; bucket = bucket.next
|
||||
{
|
||||
verify( bucket.blocks != nil, "Found corrupted bucket" )
|
||||
}
|
||||
}
|
||||
|
||||
pool_validate_ownership :: proc( using self : Pool, block : [] byte ) -> b32
|
||||
{
|
||||
profile(#procedure)
|
||||
|
@ -106,7 +106,7 @@ slab_destroy :: proc( using self : Slab )
|
||||
free( self.header, backing )
|
||||
}
|
||||
|
||||
slab_alloc :: proc( using self : Slab,
|
||||
slab_alloc :: proc( self : Slab,
|
||||
size : uint,
|
||||
alignment : uint,
|
||||
zero_memory := true,
|
||||
@ -116,24 +116,26 @@ slab_alloc :: proc( using self : Slab,
|
||||
// profile(#procedure)
|
||||
pool : Pool
|
||||
id : u32 = 0
|
||||
for ; id < pools.idx; id += 1 {
|
||||
pool = pools.items[id]
|
||||
for ; id < self.pools.idx; id += 1 {
|
||||
pool = self.pools.items[id]
|
||||
|
||||
if pool.block_size >= size && pool.alignment >= alignment {
|
||||
break
|
||||
}
|
||||
}
|
||||
verify( id < pools.idx, "There is not a size class in the slab's policy to satisfy the requested allocation" )
|
||||
verify( id < self.pools.idx, "There is not a size class in the slab's policy to satisfy the requested allocation" )
|
||||
|
||||
verify( pool.header != nil, "Requested alloc not supported by the slab allocator", location = loc )
|
||||
|
||||
block : []byte
|
||||
slab_validate_pools( self )
|
||||
block, alloc_error = pool_grab(pool)
|
||||
if alloc_error != .None {
|
||||
slab_validate_pools( self )
|
||||
if block == nil || alloc_error != .None {
|
||||
ensure(false, "Bad block from pool")
|
||||
return nil, alloc_error
|
||||
}
|
||||
// log( str_fmt_tmp("%v: Retrieved block: %p %d", dbg_name, raw_data(block), len(block) ))
|
||||
log( str_fmt_tmp("%v: Retrieved block: %p %d", self.dbg_name, raw_data(block), len(block) ))
|
||||
|
||||
data = byte_slice(raw_data(block), size)
|
||||
if zero_memory {
|
||||
@ -196,7 +198,9 @@ slab_resize :: proc( using self : Slab,
|
||||
|
||||
if zero_memory && new_size > old_size {
|
||||
to_zero := byte_slice( new_data_ptr, int(new_size - old_size) )
|
||||
slab_validate_pools( self )
|
||||
slice.zero( to_zero )
|
||||
slab_validate_pools( self )
|
||||
log( str_fmt_tmp("Zeroed memory - Range(%p to %p)", new_data_ptr, cast(rawptr) (uintptr(new_data_ptr) + uintptr(new_size - old_size))))
|
||||
}
|
||||
return
|
||||
@ -204,7 +208,9 @@ slab_resize :: proc( using self : Slab,
|
||||
|
||||
// We'll need to provide an entirely new block, so the data will need to be copied over.
|
||||
new_block : []byte
|
||||
slab_validate_pools( self )
|
||||
new_block, alloc_error = pool_grab( pool_resize )
|
||||
slab_validate_pools( self )
|
||||
if new_block == nil {
|
||||
ensure(false, "Retreived a null block")
|
||||
return
|
||||
@ -223,7 +229,7 @@ slab_resize :: proc( using self : Slab,
|
||||
pool_release( pool_old, data )
|
||||
}
|
||||
|
||||
new_data = byte_slice( raw_data(new_block), int(old_size) )
|
||||
new_data = new_block[ :new_size]
|
||||
return
|
||||
}
|
||||
|
||||
@ -235,6 +241,15 @@ slab_reset :: proc( slab : Slab )
|
||||
}
|
||||
}
|
||||
|
||||
slab_validate_pools :: proc( slab : Slab )
|
||||
{
|
||||
slab := slab
|
||||
for id in 0 ..< slab.pools.idx {
|
||||
pool := slab.pools.items[id]
|
||||
pool_validate( pool )
|
||||
}
|
||||
}
|
||||
|
||||
slab_allocator_proc :: proc(
|
||||
allocator_data : rawptr,
|
||||
mode : AllocatorMode,
|
||||
|
@ -58,7 +58,7 @@ str_cache_init :: proc( /*allocator : Allocator*/ ) -> ( cache : StringCache ) {
|
||||
cache.slab, alloc_error = slab_init( & policy, allocator = persistent_allocator(), dbg_name = dbg_name )
|
||||
verify(alloc_error == .None, "Failed to initialize the string cache" )
|
||||
|
||||
cache.table, alloc_error = zpl_hmap_init_reserve( StringCached, persistent_slab_allocator(), 64 * Kilobyte )
|
||||
cache.table, alloc_error = zpl_hmap_init_reserve( StringCached, persistent_slab_allocator(), 8 )
|
||||
return
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ str_intern :: proc(
|
||||
) -> StringCached
|
||||
{
|
||||
// profile(#procedure)
|
||||
cache := get_state().string_cache
|
||||
cache := & get_state().string_cache
|
||||
|
||||
key := u64( crc32( transmute([]byte) content ))
|
||||
result := zpl_hmap_get( & cache.table, key )
|
||||
@ -92,9 +92,13 @@ str_intern :: proc(
|
||||
runes, alloc_error = to_runes( content, slab_allocator(cache.slab) )
|
||||
verify( alloc_error == .None, "String cache had a backing allocator error" )
|
||||
|
||||
slab_validate_pools( get_state().persistent_slab )
|
||||
|
||||
// result, alloc_error = zpl_hmap_set( & cache.table, key, StringCached { transmute(string) byte_slice(str_mem, length), runes } )
|
||||
result, alloc_error = zpl_hmap_set( & cache.table, key, StringCached { transmute(string) str_mem, runes } )
|
||||
verify( alloc_error == .None, "String cache had a backing allocator error" )
|
||||
|
||||
slab_validate_pools( get_state().persistent_slab )
|
||||
}
|
||||
// profile_end()
|
||||
|
||||
|
@ -45,6 +45,10 @@ Range2 :: struct #raw_union{
|
||||
x0, y0 : f32,
|
||||
x1, y1 : f32,
|
||||
},
|
||||
|
||||
// TODO(Ed) : Test these
|
||||
array : [4]f32,
|
||||
mat : matrix[2, 2] f32,
|
||||
}
|
||||
|
||||
range2 :: #force_inline proc "contextless" ( a, b : Vec2 ) -> Range2 {
|
||||
@ -60,6 +64,12 @@ add_range2 :: #force_inline proc "contextless" ( a, b : Range2 ) -> Range2 {
|
||||
return result
|
||||
}
|
||||
|
||||
sub_range2 :: #force_inline proc "contextless" ( a, b : Range2 ) -> Range2 {
|
||||
// result := Range2 { array = a.array - b.array }
|
||||
result := Range2 { mat = a.mat - b.mat }
|
||||
return result
|
||||
}
|
||||
|
||||
equal_range2 :: #force_inline proc "contextless" ( a, b : Range2 ) -> b32 {
|
||||
result := a.p0 == b.p0 && a.p1 == b.p1
|
||||
return b32(result)
|
||||
|
@ -89,9 +89,9 @@ PWS_ParseError :: struct {
|
||||
}
|
||||
|
||||
PWS_ParseError_Max :: 32
|
||||
PWS_TokenArray_ReserveSize :: Kilobyte * 64
|
||||
PWS_NodeArray_ReserveSize :: Kilobyte * 64
|
||||
PWS_LineArray_ReserveSize :: Kilobyte * 64
|
||||
PWS_TokenArray_ReserveSize :: 8
|
||||
PWS_NodeArray_ReserveSize :: 8
|
||||
PWS_LineArray_ReserveSize :: 8
|
||||
|
||||
// TODO(Ed) : The ast arrays should be handled by a slab allocator dedicated to PWS_ASTs
|
||||
// This can grow in undeterministic ways, persistent will get very polluted otherwise.
|
||||
|
@ -274,7 +274,7 @@ UI_Box :: struct {
|
||||
UI_Layout_Stack_Size :: 512
|
||||
UI_Style_Stack_Size :: 512
|
||||
UI_Parent_Stack_Size :: 512
|
||||
UI_Built_Boxes_Array_Size :: 512
|
||||
UI_Built_Boxes_Array_Size :: 8 * Kilobyte
|
||||
|
||||
UI_State :: struct {
|
||||
// TODO(Ed) : Use these
|
||||
|
@ -76,7 +76,7 @@ ui_compute_layout :: proc()
|
||||
parent_content.min + parent_content_size * anchor.min,
|
||||
parent_content.max - parent_content_size * anchor.max,
|
||||
)
|
||||
anchored_bounds_origin := (anchored_bounds.min + anchored_bounds.max) * 0.5
|
||||
// anchored_bounds_origin := (anchored_bounds.min + anchored_bounds.max) * 0.5
|
||||
|
||||
// 2. Apply Margins
|
||||
margins := range2(
|
||||
@ -106,7 +106,12 @@ ui_compute_layout :: proc()
|
||||
}
|
||||
|
||||
text_size : Vec2
|
||||
text_size = cast(Vec2) measure_text_size( current.text.str, style.font, style.font_size, 0 )
|
||||
if style.font_size == computed.text_size.y {
|
||||
text_size = computed.text_size
|
||||
}
|
||||
else {
|
||||
text_size = cast(Vec2) measure_text_size( current.text.str, style.font, style.font_size, 0 )
|
||||
}
|
||||
|
||||
if size_to_text {
|
||||
adjusted_size = text_size
|
||||
@ -158,8 +163,6 @@ ui_compute_layout :: proc()
|
||||
computed.padding = padding_bounds
|
||||
computed.content = content_bounds
|
||||
|
||||
// TODO(Ed): Needs a rework based on changes to rest of layout above being changed
|
||||
// Text
|
||||
if len(current.text.str) > 0
|
||||
{
|
||||
content_size := content_bounds.max - content_bounds.min
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit d9e318a22076638f91aa6c168c8c7f5f47f2ed6f
|
||||
Subproject commit fe500e29040ef741cd507c4ce250d4183fa51852
|
Loading…
Reference in New Issue
Block a user