|  |  |  | @@ -6,6 +6,9 @@ with hot-reloads... | 
		
	
		
			
				|  |  |  |  | 5-21-2024 Update: Still haven't taken the time to see why but just to add the original case for the above | 
		
	
		
			
				|  |  |  |  | was I believe exclusively when I didn't set the base addresss of vmem | 
		
	
		
			
				|  |  |  |  | OR when I was attempting to use Casey's brute force replay feature with memory. | 
		
	
		
			
				|  |  |  |  | 5-26-2024 Update: | 
		
	
		
			
				|  |  |  |  | TODO(Ed): There is a Raw_Map structure defined in base:runtime/core.odin | 
		
	
		
			
				|  |  |  |  | We can use the regulare dynamic  | 
		
	
		
			
				|  |  |  |  | --------------------------------------------------------------------------------------------------------- | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | This implementation uses two ZPL-Based Arrays to hold entires and the actual hash table. | 
		
	
	
		
			
				
					
					|  |  |  | @@ -44,11 +47,11 @@ HMapZPL :: struct ( $ Type : typeid ) { | 
		
	
		
			
				|  |  |  |  | 	entries : Array( HMapZPL_Entry(Type) ), | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_init :: proc( $ Type : typeid, allocator : Allocator ) -> ( HMapZPL( Type), AllocatorError ) { | 
		
	
		
			
				|  |  |  |  | 	return zpl_hmap_init_reserve( Type, allocator ) | 
		
	
		
			
				|  |  |  |  | hamp_zpl_init :: proc( $ Type : typeid, allocator : Allocator ) -> ( HMapZPL( Type), AllocatorError ) { | 
		
	
		
			
				|  |  |  |  | 	return hamp_zpl_init_reserve( Type, allocator ) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_init_reserve :: proc | 
		
	
		
			
				|  |  |  |  | hamp_zpl_init_reserve :: proc | 
		
	
		
			
				|  |  |  |  | ( $ Type : typeid, allocator : Allocator, num : u64, dbg_name : string = "" ) -> ( HMapZPL( Type), AllocatorError ) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	result                       : HMapZPL(Type) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -70,7 +73,7 @@ zpl_hmap_init_reserve :: proc | 
		
	
		
			
				|  |  |  |  | 	return result, AllocatorError.None | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_clear :: proc( using self : ^ HMapZPL( $ Type ) ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_clear :: proc( using self : ^ HMapZPL( $ Type ) ) { | 
		
	
		
			
				|  |  |  |  | 	for id := 0; id < table.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		table[id] = -1 | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -79,17 +82,17 @@ zpl_hmap_clear :: proc( using self : ^ HMapZPL( $ Type ) ) { | 
		
	
		
			
				|  |  |  |  | 	array_clear( entries ) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_destroy :: proc( using self : ^ HMapZPL( $ Type ) ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_destroy :: proc( using self : ^ HMapZPL( $ Type ) ) { | 
		
	
		
			
				|  |  |  |  | 	if table.data != nil && table.capacity > 0 { | 
		
	
		
			
				|  |  |  |  | 		array_free( table ) | 
		
	
		
			
				|  |  |  |  | 		array_free( entries ) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_get :: proc ( using self : ^ HMapZPL( $ Type ), key : u64 ) -> ^ Type | 
		
	
		
			
				|  |  |  |  | hamp_zpl_get :: proc ( using self : ^ HMapZPL( $ Type ), key : u64 ) -> ^ Type | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	// profile(#procedure) | 
		
	
		
			
				|  |  |  |  | 	id := zpl_hmap_find( self, key ).entry_index | 
		
	
		
			
				|  |  |  |  | 	id := hamp_zpl_find( self, key ).entry_index | 
		
	
		
			
				|  |  |  |  | 	if id >= 0 { | 
		
	
		
			
				|  |  |  |  | 		return & entries.data[id].value | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -97,35 +100,35 @@ zpl_hmap_get :: proc ( using self : ^ HMapZPL( $ Type ), key : u64 ) -> ^ Type | 
		
	
		
			
				|  |  |  |  | 	return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_map :: proc( using self : ^ HMapZPL( $ Type), map_proc : HMapZPL_MapProc ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_map :: proc( using self : ^ HMapZPL( $ Type), map_proc : HMapZPL_MapProc ) { | 
		
	
		
			
				|  |  |  |  | 	ensure( map_proc != nil, "Mapping procedure must not be null" ) | 
		
	
		
			
				|  |  |  |  | 	for id := 0; id < entries.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		map_proc( Type, entries[id].key, entries[id].value ) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_map_mut :: proc( using self : ^ HMapZPL( $ Type), map_proc : HMapZPL_MapMutProc ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_map_mut :: proc( using self : ^ HMapZPL( $ Type), map_proc : HMapZPL_MapMutProc ) { | 
		
	
		
			
				|  |  |  |  | 	ensure( map_proc != nil, "Mapping procedure must not be null" ) | 
		
	
		
			
				|  |  |  |  | 	for id := 0; id < entries.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		map_proc( Type, entries[id].key, & entries[id].value ) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_grow :: proc( using self : ^ HMapZPL( $ Type ) ) -> AllocatorError { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_grow :: proc( using self : ^ HMapZPL( $ Type ) ) -> AllocatorError { | 
		
	
		
			
				|  |  |  |  | 	new_num := array_grow_formula( entries.num ) | 
		
	
		
			
				|  |  |  |  | 	return zpl_hmap_rehash( self, new_num ) | 
		
	
		
			
				|  |  |  |  | 	return hamp_zpl_rehash( self, new_num ) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorError | 
		
	
		
			
				|  |  |  |  | hamp_zpl_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorError | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	profile(#procedure) | 
		
	
		
			
				|  |  |  |  | 	// For now the prototype should never allow this to happen. | 
		
	
		
			
				|  |  |  |  | 	ensure( false, "ZPL HMAP IS REHASHING" ) | 
		
	
		
			
				|  |  |  |  | 	last_added_index : i64 | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	new_ht, init_result := zpl_hmap_init_reserve( Type, ht.table.backing, new_num, ht.table.dbg_name ) | 
		
	
		
			
				|  |  |  |  | 	new_ht, init_result := hamp_zpl_init_reserve( Type, ht.table.backing, new_num, ht.table.dbg_name ) | 
		
	
		
			
				|  |  |  |  | 	if init_result != AllocatorError.None { | 
		
	
		
			
				|  |  |  |  | 		ensure( false, "New zpl_hmap failed to allocate" ) | 
		
	
		
			
				|  |  |  |  | 		ensure( false, "New hamp_zpl failed to allocate" ) | 
		
	
		
			
				|  |  |  |  | 		return init_result | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -133,8 +136,8 @@ zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE | 
		
	
		
			
				|  |  |  |  | 		find_result : HMapZPL_FindResult | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		entry           := & ht.entries.data[id] | 
		
	
		
			
				|  |  |  |  | 		find_result      = zpl_hmap_find( & new_ht, entry.key ) | 
		
	
		
			
				|  |  |  |  | 		last_added_index = zpl_hmap_add_entry( & new_ht, entry.key ) | 
		
	
		
			
				|  |  |  |  | 		find_result      = hamp_zpl_find( & new_ht, entry.key ) | 
		
	
		
			
				|  |  |  |  | 		last_added_index = hamp_zpl_add_entry( & new_ht, entry.key ) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if find_result.prev_index < 0 { | 
		
	
		
			
				|  |  |  |  | 			new_ht.table.data[ find_result.hash_index ] = last_added_index | 
		
	
	
		
			
				
					
					|  |  |  | @@ -147,13 +150,13 @@ zpl_hmap_rehash :: proc( ht : ^ HMapZPL( $ Type ), new_num : u64 ) -> AllocatorE | 
		
	
		
			
				|  |  |  |  | 		new_ht.entries.data[ last_added_index ].value = entry.value | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	zpl_hmap_destroy( ht ) | 
		
	
		
			
				|  |  |  |  | 	hamp_zpl_destroy( ht ) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	(ht ^) = new_ht | 
		
	
		
			
				|  |  |  |  | 	return AllocatorError.None | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) ) | 
		
	
		
			
				|  |  |  |  | hamp_zpl_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) ) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	for id := 0; id < entries.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		entries[id].Next = -1; | 
		
	
	
		
			
				
					
					|  |  |  | @@ -163,7 +166,7 @@ zpl_hmap_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) ) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	for id := 0; id < entries.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		entry       := & entries[id] | 
		
	
		
			
				|  |  |  |  | 		find_result := zpl_hmap_find( entry.key ) | 
		
	
		
			
				|  |  |  |  | 		find_result := hamp_zpl_find( entry.key ) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 		if find_result.prev_index < 0 { | 
		
	
		
			
				|  |  |  |  | 			table[ find_result.hash_index ] = id | 
		
	
	
		
			
				
					
					|  |  |  | @@ -175,45 +178,45 @@ zpl_hmap_rehash_fast :: proc( using self : ^ HMapZPL( $ Type ) ) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Used when the address space of the allocator changes and the backing reference must be updated | 
		
	
		
			
				|  |  |  |  | zpl_hmap_reload :: proc( using self : ^HMapZPL($Type), new_backing : Allocator ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_reload :: proc( using self : ^HMapZPL($Type), new_backing : Allocator ) { | 
		
	
		
			
				|  |  |  |  | 	table.backing   = new_backing | 
		
	
		
			
				|  |  |  |  | 	entries.backing = new_backing | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_remove :: proc( self : ^ HMapZPL( $ Type ), key : u64 ) { | 
		
	
		
			
				|  |  |  |  | 	find_result := zpl_hmap_find( key ) | 
		
	
		
			
				|  |  |  |  | hamp_zpl_remove :: proc( self : ^ HMapZPL( $ Type ), key : u64 ) { | 
		
	
		
			
				|  |  |  |  | 	find_result := hamp_zpl_find( key ) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if find_result.entry_index >= 0 { | 
		
	
		
			
				|  |  |  |  | 		array_remove_at( & entries, find_result.entry_index ) | 
		
	
		
			
				|  |  |  |  | 		zpl_hmap_rehash_fast( self ) | 
		
	
		
			
				|  |  |  |  | 		hamp_zpl_rehash_fast( self ) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_remove_entry :: proc( using self : ^ HMapZPL( $ Type ), id : i64 ) { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_remove_entry :: proc( using self : ^ HMapZPL( $ Type ), id : i64 ) { | 
		
	
		
			
				|  |  |  |  | 	array_remove_at( & entries, id ) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_set :: proc( using self : ^ HMapZPL( $ Type), key : u64, value : Type ) -> (^ Type, AllocatorError) | 
		
	
		
			
				|  |  |  |  | hamp_zpl_set :: proc( using self : ^ HMapZPL( $ Type), key : u64, value : Type ) -> (^ Type, AllocatorError) | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	// profile(#procedure) | 
		
	
		
			
				|  |  |  |  | 	id          : i64 = 0 | 
		
	
		
			
				|  |  |  |  | 	find_result : HMapZPL_FindResult | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if zpl_hmap_full( self ) | 
		
	
		
			
				|  |  |  |  | 	if hamp_zpl_full( self ) | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		grow_result := zpl_hmap_grow( self ) | 
		
	
		
			
				|  |  |  |  | 		grow_result := hamp_zpl_grow( self ) | 
		
	
		
			
				|  |  |  |  | 		if grow_result != AllocatorError.None { | 
		
	
		
			
				|  |  |  |  | 				return nil, grow_result | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	find_result = zpl_hmap_find( self, key ) | 
		
	
		
			
				|  |  |  |  | 	find_result = hamp_zpl_find( self, key ) | 
		
	
		
			
				|  |  |  |  | 	if find_result.entry_index >= 0 { | 
		
	
		
			
				|  |  |  |  | 		id = find_result.entry_index | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	else | 
		
	
		
			
				|  |  |  |  | 	{ | 
		
	
		
			
				|  |  |  |  | 		id = zpl_hmap_add_entry( self, key ) | 
		
	
		
			
				|  |  |  |  | 		id = hamp_zpl_add_entry( self, key ) | 
		
	
		
			
				|  |  |  |  | 		if find_result.prev_index >= 0 { | 
		
	
		
			
				|  |  |  |  | 			entries.data[ find_result.prev_index ].next = id | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
	
		
			
				
					
					|  |  |  | @@ -224,15 +227,15 @@ zpl_hmap_set :: proc( using self : ^ HMapZPL( $ Type), key : u64, value : Type ) | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	entries.data[id].value = value | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	if zpl_hmap_full( self ) { | 
		
	
		
			
				|  |  |  |  | 		alloc_error := zpl_hmap_grow( self ) | 
		
	
		
			
				|  |  |  |  | 	if hamp_zpl_full( self ) { | 
		
	
		
			
				|  |  |  |  | 		alloc_error := hamp_zpl_grow( self ) | 
		
	
		
			
				|  |  |  |  | 		return & entries.data[id].value, alloc_error | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	return & entries.data[id].value, AllocatorError.None | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_slot :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_slot :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 { | 
		
	
		
			
				|  |  |  |  | 	for id : i64 = 0; id < table.num; id += 1 { | 
		
	
		
			
				|  |  |  |  | 		if table.data[id] == key                { | 
		
	
		
			
				|  |  |  |  | 			return id | 
		
	
	
		
			
				
					
					|  |  |  | @@ -241,14 +244,14 @@ zpl_hmap_slot :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 { | 
		
	
		
			
				|  |  |  |  | 	return -1 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_add_entry :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_add_entry :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> i64 { | 
		
	
		
			
				|  |  |  |  | 	entry : HMapZPL_Entry(Type) = { key, -1, {} } | 
		
	
		
			
				|  |  |  |  | 	id    := cast(i64) entries.num | 
		
	
		
			
				|  |  |  |  | 	array_append( & entries, entry ) | 
		
	
		
			
				|  |  |  |  | 	return id | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_find :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> HMapZPL_FindResult | 
		
	
		
			
				|  |  |  |  | hamp_zpl_find :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> HMapZPL_FindResult | 
		
	
		
			
				|  |  |  |  | { | 
		
	
		
			
				|  |  |  |  | 	// profile(#procedure) | 
		
	
		
			
				|  |  |  |  | 	result : HMapZPL_FindResult = { -1, -1, -1 } | 
		
	
	
		
			
				
					
					|  |  |  | @@ -272,7 +275,7 @@ zpl_hmap_find :: proc( using self : ^ HMapZPL( $ Type), key : u64 ) -> HMapZPL_F | 
		
	
		
			
				|  |  |  |  | 	return result | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | zpl_hmap_full :: proc( using self : ^ HMapZPL( $ Type) ) -> b32 { | 
		
	
		
			
				|  |  |  |  | hamp_zpl_full :: proc( using self : ^ HMapZPL( $ Type) ) -> b32 { | 
		
	
		
			
				|  |  |  |  | 	critical_load := u64(HMapZPL_CritialLoadScale * cast(f64) table.num) | 
		
	
		
			
				|  |  |  |  | 	result : b32 = entries.num > critical_load | 
		
	
		
			
				|  |  |  |  | 	return result | 
		
	
	
		
			
				
					
					|  |  |  |   |