put in its own file
authorhgn <hgodden00@gmail.com>
Tue, 13 Jun 2023 16:20:55 +0000 (17:20 +0100)
committerhgn <hgodden00@gmail.com>
Tue, 13 Jun 2023 16:20:55 +0000 (17:20 +0100)
addon.c
addon.h
addon_cache.c [new file with mode: 0644]
addon_cache.h [new file with mode: 0644]
ent_skateshop.c
ent_skateshop.h
skaterift.c
skaterift.h
workshop_types.h

diff --git a/addon.c b/addon.c
index b599c304a04e2c91f3965460774db4ba22bd6864..fe6693f89adf847a9f4bfad27c057d660eef7337 100644 (file)
--- 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 f1d466e10f7938237331c95a5e3d565e7af760e8..85b5014bf7c9d7e036a837cd6f6067d464d536e5 100644 (file)
--- 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 (file)
index 0000000..1dd4ecd
--- /dev/null
@@ -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 = ic<cache->count? 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 (file)
index 0000000..02df822
--- /dev/null
@@ -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 */
index 39dec86a993115c9058cdd17118f9a8ae2b24cb6..fbab58833d7dc542bbb18e6cada266bdb2e52f32 100644 (file)
@@ -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; i<SKATESHOP_BOARD_CACHE_MAX; i++ ){
-      struct cache_board *cache_ptr = &global_skateshop.cache[i];
-
-      if( cache_ptr->state == 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; i<SKATESHOP_BOARD_CACHE_MAX; i++ ){
-      struct cache_board *cache_ptr = &global_skateshop.cache[i];
+   for( u32 i=0; i<CACHE_BOARD_MAX; i++ ){
+      struct cache_board *cache_ptr = &addon_system.boards[i];
 
-      SDL_AtomicLock( &global_skateshop.sl_cache_access );
+      SDL_AtomicLock( &addon_system.sl_cache );
       if( cache_ptr->state == 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<SKATESHOP_BOARD_CACHE_MAX; ib++ ){
-      i32 ia = ib-1, ic = ib+1;
-      struct cache_board *arr = global_skateshop.cache,
-                         *pb = &arr[ib],
-                         *pa = ia>=0? &arr[ia]: NULL,
-                         *pc = ic<SKATESHOP_BOARD_CACHE_MAX? &arr[ic]: NULL;
-      pb->left = 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; i<CACHE_BOARD_MAX; i++ ){
+      struct cache_board *board = &addon_system.boards[i];
+      board->state = 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; i<SKATESHOP_VIEW_SLOT_MAX; i++ ){
       struct shop_view_slot *slot = &global_skateshop.shop_view_slots[i];
 
@@ -644,7 +577,7 @@ VG_STATIC void skateshop_render_boardshop(void)
       else if( slot->cache_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<slot_count; i++ ){
index 12cfd218e1b1675270673c552f262dba388c1c44..ff52db0f1380530b4d0c9f6d2c86622dbddf35c7 100644 (file)
@@ -8,7 +8,6 @@
 #include "workshop.h"
 #include "addon.h"
 
-#define SKATESHOP_BOARD_CACHE_MAX  10
 #define SKATESHOP_VIEW_SLOT_MAX    6
 
 struct{
@@ -18,27 +17,6 @@ struct{
    int active;
    float factive;
 
-   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;
-
-      u32 ref_count;
-      
-      struct cache_board *left, *right;
-      /* double last_use_time; */
-   }
-   *cache, *cache_head, *cache_tail;
-
-   SDL_SpinLock sl_cache_access;
-
    struct shop_view_slot{
       struct cache_board *cache_ptr;
       float view_blend;
@@ -61,8 +39,5 @@ struct{
 static global_skateshop={.render={.reg_id=0xffffffff,.world_reg=0xffffffff}};
 
 VG_STATIC void global_skateshop_exit(void);
-VG_STATIC void watch_cache_board( struct cache_board *ptr );
-VG_STATIC void unwatch_cache_board( struct cache_board *ptr );
-VG_STATIC struct cache_board *lru_volatile_cache_board(void);
 
 #endif /* ENT_SKATESHOP_H */
index e510a1f6a7a5167425f5e81e4c6f80df43fb636f..46cde31382876a9c50dde861363263285da69f0b 100644 (file)
@@ -244,7 +244,8 @@ VG_STATIC void vg_load(void)
                              query_workshop_id, query_local_folder );
    if( reg_id != 0xffffffff ){
       localplayer.board_view_slot = skateshop_cache_fetch_board( reg_id );
-      watch_cache_board( localplayer.board_view_slot );
+      addon_cache_watch( &addon_system.board_cache,
+                          localplayer.board_view_slot );
    }
 
    board_processview_thread(NULL); /* END_OP!! */
index c13c78b7fb3d455a35955f9ffdb7a43243b83372..e7e2b078f6f3b845f92233cbf0a6e39519d7b1d5 100644 (file)
@@ -12,6 +12,7 @@
 #include "common.h"
 #include "world.h"
 #include "addon.h"
+#include "addon_cache.h"
 
 struct{
    enum async_operation{
index 8bdd1b05c87dc32e16210ed800e57e04e08f0af8..b587ff45823f5986b363dba460f92b5208fbbbfa 100644 (file)
@@ -5,7 +5,8 @@ enum workshop_file_type{
    k_workshop_file_type_none   = 0,
    k_workshop_file_type_board  = 1,
    k_workshop_file_type_world  = 2,
-   k_workshop_file_type_max    = 8
+   k_workshop_file_type_player = 3,
+   k_workshop_file_type_max
 };
 
 #endif /* WORKSHOP_TYPES_H */