From 8310bba397e006af89d76c155c1a9ce45306c337 Mon Sep 17 00:00:00 2001 From: jacob Date: Wed, 14 May 2025 14:05:21 -0500 Subject: [PATCH] avoid mid-scope change to reloaded sprite --- src/sprite.c | 73 ++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/src/sprite.c b/src/sprite.c index 56bc6336..916c5571 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -91,6 +91,7 @@ struct cache_entry { struct cache_bin { struct sys_mutex mutex; struct cache_entry *first; + struct cache_entry *last; }; struct cache { @@ -798,58 +799,44 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_lookup_touch(struct sprite_s __prof; struct sprite_scope_cache_ref *scope_ref = NULL; - struct cache_entry *entry = NULL; - struct cache_entry *nonmatching = NULL; - struct cache_entry **nonmatching_next = NULL; struct cache_entry_hash hash = cache_entry_hash_from_tag_hash(tag.hash, kind); u64 bin_index = hash.v % CACHE_BINS_COUNT; struct cache_bin *bin = &G.cache.bins[bin_index]; /* Lookup */ - /* TODO: Spinlock */ { struct sys_lock bin_lock = sys_mutex_lock_s(&bin->mutex); - nonmatching_next = &bin->first; - entry = *nonmatching_next; - while (entry) { - b32 match = false; + struct cache_entry *match = NULL; + for (struct cache_entry *entry = bin->first; entry; entry = entry->next_in_bin) { if (entry->hash.v == hash.v) { #if RESOURCE_RELOADING - scope_ref = scope_get_ref_or_null(scope, entry, bin_index, &bin_lock); - if (scope_ref) { - match = true; - } else { - if (atomic_i32_eval(&entry->out_of_date)) { - /* If entry is out of date and the scope doesn't already hold a reference to it, then ignore entry */ - } else { - match = true; - scope_ref = scope_ensure_ref(scope, entry, bin_index, &bin_lock); - } + b32 has_ref = scope_get_ref_or_null(scope, entry, bin_index, &bin_lock) != NULL; + if (has_ref) { + match = entry; + break; + } else if (!atomic_i32_eval(&entry->out_of_date)) { + match = entry; } #else - scope_ref = scope_ensure_ref(scope, entry, ref_node, &bin_lock); - match = true; + match = entry; + break; #endif } - - if (match) { - break; - } else { - nonmatching = entry; - nonmatching_next = &nonmatching->next_in_bin; - entry = *nonmatching_next; - } + } + if (match) { + scope_ref = scope_ensure_ref(scope, match, bin_index, &bin_lock); } sys_mutex_unlock(&bin_lock); } /* Allocate new entry if necessary */ - if (!entry) { + if (!scope_ref) { __profscope(entry_lookup_allocate); struct sys_lock bin_lock = sys_mutex_lock_e(&bin->mutex); { /* Alloc entry */ + struct cache_entry *entry = NULL; { struct sys_lock pool_lock = sys_mutex_lock_e(&G.cache.entry_pool_mutex); if (G.cache.entry_pool_first_free) { @@ -864,10 +851,14 @@ INTERNAL struct sprite_scope_cache_ref *cache_entry_lookup_touch(struct sprite_s /* Init node and add to bin */ scope_ref = scope_ensure_ref(scope, entry, bin_index, &bin_lock); - *nonmatching_next = entry; - if (nonmatching) { - nonmatching->next_in_bin = entry; - entry->prev_in_bin = nonmatching; + { + if (bin->last) { + bin->last->next_in_bin = entry; + entry->prev_in_bin = bin->last; + } else { + bin->first = entry; + } + bin->last = entry; } entry->hash = cache_entry_hash_from_tag_hash(tag.hash, kind); entry->kind = kind; @@ -1098,7 +1089,7 @@ INTERNAL RESOURCE_WATCH_CALLBACK_FUNC_DEF(sprite_resource_watch_callback, name) { for (struct cache_entry *n = bin->first; n; n = n->next_in_bin) { if (n->hash.v == hash.v) { - logf_info("Sprite resource file \"%F\" has changed and will be reloaded.", FMT_STR(name)); + logf_info("Sprite resource file \"%F\" has changed.", FMT_STR(name)); atomic_i32_eval_exchange(&n->out_of_date, 1); } } @@ -1218,13 +1209,17 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(sprite_evictor_thread_entry_point, arg) /* Cache node has been referenced since scan, skip node. */ } else if (cache_over_budget_target || last_ref_cycle == 0) { /* Remove from cache bin */ - if (entry->prev_in_bin) { - entry->prev_in_bin->next_in_bin = entry->next_in_bin; + struct cache_entry *prev = entry->prev_in_bin; + struct cache_entry *next = entry->next_in_bin; + if (prev) { + prev->next_in_bin = next; } else { - bin->first = entry->next_in_bin; + bin->first = next; } - if (entry->next_in_bin) { - entry->next_in_bin->prev_in_bin = entry->prev_in_bin; + if (next) { + next->prev_in_bin = prev; + } else { + bin->last = prev; } atomic_u64_eval_add_i64(&G.cache.memory_usage, -((i64)entry->memory_usage));