avoid mid-scope change to reloaded sprite
This commit is contained in:
parent
885652082d
commit
8310bba397
73
src/sprite.c
73
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));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user