From 4a567dd9ef3bd63fb924d80fd2e09323b99d0a34 Mon Sep 17 00:00:00 2001 From: hgn Date: Tue, 13 Jun 2023 17:20:55 +0100 Subject: [PATCH] put in its own file --- addon.c | 2 + addon.h | 32 +++++++++- addon_cache.c | 80 ++++++++++++++++++++++++ addon_cache.h | 29 +++++++++ ent_skateshop.c | 157 ++++++++++++++--------------------------------- ent_skateshop.h | 25 -------- skaterift.c | 3 +- skaterift.h | 1 + workshop_types.h | 3 +- 9 files changed, 192 insertions(+), 140 deletions(-) create mode 100644 addon_cache.c create mode 100644 addon_cache.h diff --git a/addon.c b/addon.c index b599c30..fe6693f 100644 --- a/addon.c +++ b/addon.c @@ -7,6 +7,8 @@ #include "workshop_types.h" #include "workshop.h" +#include "addon_cache.c" + static u32 addon_count( enum workshop_file_type type ){ return addon_system.registry_type_counts[ type ]; } diff --git a/addon.h b/addon.h index f1d466e..85b5014 100644 --- a/addon.h +++ b/addon.h @@ -4,9 +4,20 @@ #include "common.h" #include "vg/vg_steam_ugc.h" #include "workshop_types.h" -#define ADDON_MOUNTED_MAX 128 +#include "addon_cache.h" + +#include "world.h" +#include "player.h" + #define ADDON_FOLDERNAME_MAX 64 +/* total count that we have knowledge of */ +#define ADDON_MOUNTED_MAX 128 + +/* in memory and loaded stuffs */ +#define CACHE_BOARD_MAX 10 +#define CACHE_PLAYER_MAX 10 + typedef struct addon_reg addon_reg; struct { struct addon_reg{ @@ -32,6 +43,25 @@ struct { /* deffered: updates in main thread */ u32 registry_type_counts[k_workshop_file_type_max]; + + /* caches */ + struct cache_board{ + enum cache_board_state{ + k_cache_board_state_none, + k_cache_board_state_loaded, + k_cache_board_state_load_request + } + state; + struct player_board board; + u32 reg_index; + addon_reg *reg_ptr; + + addon_cache_node cachenode; + } + *boards; + addon_cache board_cache; + + SDL_SpinLock sl_cache; } static addon_system; diff --git a/addon_cache.c b/addon_cache.c new file mode 100644 index 0000000..1dd4ecd --- /dev/null +++ b/addon_cache.c @@ -0,0 +1,80 @@ +#ifndef ADDON_CACHE_C +#define ADDON_CACHE_C + +#include "addon_cache.h" + +static addon_cache_node *addon_cache_nodeptr( addon_cache *cache, void *item ){ + if( !item ) return NULL; + else return item + cache->offset; +} + +static void *addon_cache_item( addon_cache *cache, u16 index ){ + if( index == ADDON_CACHE_NIL ) return NULL; + else return cache->buffer + cache->stride*(size_t)index; +} + +static void addon_cache_init( addon_cache *cache ){ + cache->head = 0; + cache->tail = cache->count -1; + for( i32 ib=0; ib < cache->count; ib++ ){ + void *vb = addon_cache_item( cache, ib ); + addon_cache_node *nb = addon_cache_nodeptr( cache, vb ); + + i32 ia = ib-1, ic = ib+1; + nb->l = ia>=0? ia: ADDON_CACHE_NIL, + nb->r = iccount? ic: ADDON_CACHE_NIL; + nb->ref_count = 0; + } +} + +static u16 addon_item_index( addon_cache *cache, void *item ){ + return (item - cache->buffer) / cache->stride; +} + +static void *addon_cache_lru( addon_cache *cache ){ + u16 head = cache->head; + if( head == ADDON_CACHE_NIL ) return NULL; + + void *item = addon_cache_item( cache, head ); + addon_cache_node *node = addon_cache_nodeptr( cache, item ); + + if( cache->head == cache->tail ) cache->tail = ADDON_CACHE_NIL; + cache->head = node->r; + + node->l = ADDON_CACHE_NIL; + node->r = ADDON_CACHE_NIL; + return item; +} + +static void addon_cache_watch( addon_cache *cache, void *item ){ + addon_cache_node *node = addon_cache_nodeptr( cache, item ); + + if( node->ref_count >= 32 ) + vg_fatal_error( "dynamic board watch missmatch (limit is 32)\n" ); + + node->ref_count ++; +} + +/* if after this no more watches, places back into the volatile list */ +static void addon_cache_unwatch( addon_cache *cache, void *item ){ + addon_cache_node *node = addon_cache_nodeptr( cache, item ); + + if( node->ref_count == 0 ) + vg_fatal_error( "dynamic board unwatch missmatch (no watchers)\n" ); + + node->ref_count --; + if( !node->ref_count ){ + void *item_head = addon_cache_item( cache, cache->head ), + *item_tail = addon_cache_item( cache, cache->tail ); + addon_cache_node *head = addon_cache_nodeptr( cache, item_head ), + *tail = addon_cache_nodeptr( cache, item_tail ); + + u16 index = addon_item_index( cache, item ); + if( tail ) tail->r = index; + node->l = cache->tail; + cache->tail = index; + if( !head ) cache->head = index; + } +} + +#endif /* ADDON_CACHE_C */ diff --git a/addon_cache.h b/addon_cache.h new file mode 100644 index 0000000..02df822 --- /dev/null +++ b/addon_cache.h @@ -0,0 +1,29 @@ +#ifndef ADDON_CACHE_H +#define ADDON_CACHE_H + +/* cache for loaded addons */ +#define ADDON_CACHE_NIL 0xffff + +typedef struct addon_cache addon_cache; +typedef struct addon_cache_node addon_cache_node; + +/* this goes in your structures */ +struct addon_cache_node { + u16 l, r, ref_count; +}; + +struct addon_cache { + void *buffer; /* array which holds the real data */ + u16 count, head, tail; + size_t stride, offset; +}; + +static addon_cache_node *addon_cache_nodeptr( addon_cache *cache, void *item ); +static void *addon_cache_item( addon_cache *cache, u16 index ); +static void addon_cache_init( addon_cache *cache ); +static u16 addon_item_index( addon_cache *cache, void *item ); +static void *addon_cache_lru( addon_cache *cache ); +static void addon_cache_watch( addon_cache *cache, void *item ); +static void addon_cache_unwatch( addon_cache *cache, void *item ); + +#endif /* ADDON_CACHE_H */ diff --git a/ent_skateshop.c b/ent_skateshop.c index 39dec86..fbab588 100644 --- a/ent_skateshop.c +++ b/ent_skateshop.c @@ -43,29 +43,9 @@ VG_STATIC struct cache_board *skateshop_cache_fetch_board( u32 registry_index ) } } -#if 0 - /* lru eviction. should be a linked list maybe... */ - double min_time = 1e300; - struct cache_board *min_board = NULL; - - SDL_AtomicLock( &global_skateshop.sl_cache_access ); - for( u32 i=0; istate == k_cache_board_state_load_request ) continue; - if( cache_ptr->ref_count ) continue; - - if( cache_ptr->last_use_time < min_time ){ - min_time = cache_ptr->last_use_time; - min_board = cache_ptr; - } - } -#else - - SDL_AtomicLock( &global_skateshop.sl_cache_access ); - struct cache_board *min_board = lru_volatile_cache_board(); - -#endif + SDL_AtomicLock( &addon_system.sl_cache ); + struct cache_board *min_board = + addon_cache_lru( &addon_system.board_cache ); if( min_board ){ if( min_board->state == k_cache_board_state_loaded ){ @@ -83,14 +63,13 @@ VG_STATIC struct cache_board *skateshop_cache_fetch_board( u32 registry_index ) min_board->reg_ptr = reg; min_board->reg_index = registry_index; - min_board->ref_count = 0; min_board->state = k_cache_board_state_load_request; } else{ vg_error( "No free boards to load registry!\n" ); } - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); return min_board; } @@ -102,10 +81,13 @@ VG_STATIC void skateshop_update_viewpage(void) struct shop_view_slot *slot = &global_skateshop.shop_view_slots[i]; u32 request_id = page*SKATESHOP_VIEW_SLOT_MAX + i; - if( slot->cache_ptr ) unwatch_cache_board( slot->cache_ptr ); + addon_cache *cache = &addon_system.board_cache; + if( slot->cache_ptr ) + addon_cache_unwatch( cache, slot->cache_ptr ); slot->cache_ptr = skateshop_cache_fetch_board( request_id ); - if( slot->cache_ptr ) watch_cache_board( slot->cache_ptr ); + if( slot->cache_ptr ) + addon_cache_watch( cache, slot->cache_ptr ); } } @@ -119,12 +101,12 @@ VG_STATIC void skateshop_update_viewpage(void) */ VG_STATIC void skateshop_async_board_loaded( void *payload, u32 size ) { - SDL_AtomicLock( &global_skateshop.sl_cache_access ); + SDL_AtomicLock( &addon_system.sl_cache ); struct cache_board *cache_ptr = payload; cache_ptr->state = k_cache_board_state_loaded; cache_ptr->reg_ptr->userdata = cache_ptr; - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); vg_success( "Async board loaded (%s)\n", cache_ptr->reg_ptr->foldername ); } @@ -137,20 +119,20 @@ VG_STATIC void workshop_visibile_load_loop(void) vg_info( "Running load loop\n" ); char path_buf[4096]; - for( u32 i=0; istate == k_cache_board_state_load_request ){ if( cache_ptr->reg_index >= addon_count(k_workshop_file_type_board) ){ /* should maybe have a different value for this case */ cache_ptr->state = k_cache_board_state_none; - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); continue; } /* continue with the request */ - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); addon_reg *reg = get_addon_from_index( k_workshop_file_type_board, cache_ptr->reg_index ); cache_ptr->reg_ptr = reg; @@ -163,10 +145,8 @@ VG_STATIC void workshop_visibile_load_loop(void) /* load content files * --------------------------------- */ - vg_str content_path = folder; - vg_msg root = {0}; root.buf = reg->metadata; root.len = reg->metadata_len; @@ -193,12 +173,12 @@ VG_STATIC void workshop_visibile_load_loop(void) continue; file_is_broken:; - SDL_AtomicLock( &global_skateshop.sl_cache_access ); + SDL_AtomicLock( &addon_system.sl_cache ); cache_ptr->state = k_cache_board_state_none; - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); } else - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); } } @@ -246,76 +226,27 @@ VG_STATIC void skateshop_op_processview(void){ * ----------------------------------------------------------------------------- */ -/* adds one more watch */ -VG_STATIC void watch_cache_board( struct cache_board *ptr ){ - if( ptr->ref_count >= 32 ){ - vg_fatal_error( "dynamic board watch missmatch (limit is 32)\n" ); - } - - ptr->ref_count ++; -} - -/* if after this no more watches, places back into the volatile list */ -VG_STATIC void unwatch_cache_board( struct cache_board *ptr ){ - if( ptr->ref_count == 0 ){ - vg_fatal_error( "dynamic board unwatch missmatch (no watchers)\n" ); - } - - ptr->ref_count --; - if( !ptr->ref_count ){ - struct cache_board *head = global_skateshop.cache_head, - *tail = global_skateshop.cache_tail; - - if( tail ) tail->right = ptr; - ptr->left = tail; - global_skateshop.cache_tail = ptr; - - if( !head ) global_skateshop.cache_head = ptr; - } -} - -/* retrieve oldest pointer from the volatile list (and remove it) */ -VG_STATIC struct cache_board *lru_volatile_cache_board(void){ - struct cache_board *head = global_skateshop.cache_head, - *tail = global_skateshop.cache_tail; - - if( head ){ - if( head == tail ) global_skateshop.cache_tail = NULL; - global_skateshop.cache_head = head->right; - - head->left = NULL; - head->right = NULL; - return head; - } - else return NULL; -} - /* * VG event init */ VG_STATIC void skateshop_init(void){ - u32 cache_size = sizeof(struct cache_board)*SKATESHOP_BOARD_CACHE_MAX; - global_skateshop.cache = vg_linear_alloc( vg_mem.rtmemory, cache_size ); - memset( global_skateshop.cache, 0, cache_size ); - - for( i32 ib=0; ib=0? &arr[ia]: NULL, - *pc = icleft = pa; - pb->right = pc; - - pb->state = k_cache_board_state_none; - pb->reg_ptr= NULL; - pb->reg_index = 0xffffffff; - pb->ref_count = 0; - } - - global_skateshop.cache_head = global_skateshop.cache; - global_skateshop.cache_tail = - &global_skateshop.cache[SKATESHOP_BOARD_CACHE_MAX-1]; + u32 cache_size = sizeof(struct cache_board)*CACHE_BOARD_MAX; + addon_system.boards = vg_linear_alloc( vg_mem.rtmemory, cache_size ); + memset( addon_system.boards, 0, cache_size ); + + for( i32 i=0; istate = k_cache_board_state_none; + board->reg_ptr= NULL; + board->reg_index = 0xffffffff; + } + + addon_cache *cache = &addon_system.board_cache; + cache->buffer = addon_system.boards; + cache->count = CACHE_BOARD_MAX; + cache->stride = sizeof( struct cache_board ); + cache->offset = offsetof( struct cache_board, cachenode ); + addon_cache_init( cache ); } VG_STATIC struct cache_board *skateshop_selected_cache_if_loaded(void) @@ -324,15 +255,15 @@ VG_STATIC struct cache_board *skateshop_selected_cache_if_loaded(void) addon_reg *reg = get_addon_from_index(k_workshop_file_type_board, global_skateshop.selected_board_id); - SDL_AtomicLock( &global_skateshop.sl_cache_access ); + SDL_AtomicLock( &addon_system.sl_cache ); if( reg->userdata ){ struct cache_board *cache_ptr = reg->userdata; if( cache_ptr->state == k_cache_board_state_loaded ){ - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); return cache_ptr; } } - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); } return NULL; @@ -492,11 +423,13 @@ VG_STATIC void global_skateshop_preupdate(void) global_skateshop.selected_board_id ); if( localplayer.board_view_slot ){ - unwatch_cache_board( localplayer.board_view_slot ); + addon_cache_unwatch( &addon_system.board_cache, + localplayer.board_view_slot ); } localplayer.board_view_slot = selected_cache; - watch_cache_board( localplayer.board_view_slot ); + addon_cache_watch( &addon_system.board_cache, + localplayer.board_view_slot ); global_skateshop_exit(); skaterift_write_savedata(); return; @@ -634,7 +567,7 @@ VG_STATIC void skateshop_render_boardshop(void) mdl_entity_id_id(shop->boards.id_display)); int visibility[ SKATESHOP_VIEW_SLOT_MAX ]; - SDL_AtomicLock( &global_skateshop.sl_cache_access ); + SDL_AtomicLock( &addon_system.sl_cache ); for( u32 i=0; icache_ptr->state != k_cache_board_state_loaded ) visibility[i] = 0; } - SDL_AtomicUnlock( &global_skateshop.sl_cache_access ); + SDL_AtomicUnlock( &addon_system.sl_cache ); /* Render loaded boards in the view slots */ for( u32 i=0; i