From 8a1e6ab2e61356ace551888aa3095a4b32834d06 Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 22 Sep 2025 15:25:01 -0700 Subject: [PATCH] extend artifact cache with non-key-included generations, to allow gracefully decaying certain computations --- src/artifact_cache/artifact_cache.c | 28 ++++++++--- src/artifact_cache/artifact_cache.h | 6 ++- src/text_cache/text_cache.c | 2 +- src/text_cache/text_cache.h | 78 ----------------------------- 4 files changed, 27 insertions(+), 87 deletions(-) diff --git a/src/artifact_cache/artifact_cache.c b/src/artifact_cache/artifact_cache.c index 0167dd49..58509d16 100644 --- a/src/artifact_cache/artifact_cache.c +++ b/src/artifact_cache/artifact_cache.c @@ -21,7 +21,7 @@ ac_init(void) //~ rjf: Cache Lookups internal void * -ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, AC_DestroyFunctionType *destroy, U64 slots_count) +ac_artifact_from_key(Access *access, String8 key, U64 gen, AC_CreateFunctionType *create, AC_DestroyFunctionType *destroy, U64 slots_count) { //- rjf: create function -> cache AC_Cache *cache = 0; @@ -69,8 +69,10 @@ ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) { B32 found = 0; + B32 need_request = 0; RWMutexScope(stripe->rw_mutex, write_mode) { + // rjf: look up node for(AC_Node *n = slot->first; n != 0; n = n->next) { if(str8_match(n->key, key, 0)) @@ -78,11 +80,19 @@ ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, found = 1; artifact = n->val; access_touch(access, &n->access_pt, stripe->cv); + if(n->gen != gen) + { + B32 got_task = (ins_atomic_u64_eval_cond_assign(&n->working_count, 1, 0) == 0); + need_request = got_task; + } break; } } + + // rjf: no node? -> create if(write_mode && !found) { + need_request = 1; AC_Node *node = stripe->free; if(node) { @@ -99,11 +109,9 @@ ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, node->working_count = 1; } } - if(found) - { - break; - } - else if(write_mode) + + // rjf: need request -> push + if(need_request) { MutexScope(ac_shared->req_mutex) { @@ -111,10 +119,17 @@ ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, SLLQueuePush(ac_shared->first_req, ac_shared->last_req, n); ac_shared->req_count += 1; n->v.key = str8_copy(ac_shared->req_arena, key); + n->v.gen = gen; n->v.create = create; } cond_var_broadcast(async_tick_start_cond_var); } + + // rjf: found node -> break + if(found) + { + break; + } } } @@ -240,6 +255,7 @@ ac_tick(void) { if(str8_match(n->key, reqs[idx].key, 0)) { + n->gen = reqs[idx].gen; n->val = val; ins_atomic_u64_dec_eval(&n->working_count); } diff --git a/src/artifact_cache/artifact_cache.h b/src/artifact_cache/artifact_cache.h index 9d851859..30f19c1e 100644 --- a/src/artifact_cache/artifact_cache.h +++ b/src/artifact_cache/artifact_cache.h @@ -17,6 +17,7 @@ typedef struct AC_Request AC_Request; struct AC_Request { String8 key; + U64 gen; AC_CreateFunctionType *create; }; @@ -33,8 +34,9 @@ struct AC_Node AC_Node *next; AC_Node *prev; - // rjf: key/value + // rjf: key/gen/value String8 key; + U64 gen; void *val; // rjf: metadata @@ -94,7 +96,7 @@ internal void ac_init(void); //////////////////////////////// //~ rjf: Cache Lookups -internal void *ac_artifact_from_key(Access *access, String8 key, AC_CreateFunctionType *create, AC_DestroyFunctionType *destroy, U64 slots_count); +internal void *ac_artifact_from_key(Access *access, String8 key, U64 gen, AC_CreateFunctionType *create, AC_DestroyFunctionType *destroy, U64 slots_count); //////////////////////////////// //~ rjf: Tick diff --git a/src/text_cache/text_cache.c b/src/text_cache/text_cache.c index ae39b4d3..bb24811c 100644 --- a/src/text_cache/text_cache.c +++ b/src/text_cache/text_cache.c @@ -2252,7 +2252,7 @@ txt_text_info_from_hash_lang(Access *access, U128 hash, TXT_LangKind lang) TXT_LangKind lang; } key = {hash, lang}; String8 key_string = str8_struct(&key); - TXT_Artifact *artifact = ac_artifact_from_key(access, key_string, txt_artifact_create, txt_artifact_destroy, 1024); + TXT_Artifact *artifact = ac_artifact_from_key(access, key_string, 0, txt_artifact_create, txt_artifact_destroy, 1024); TXT_TextInfo info = {0}; if(artifact != 0) { diff --git a/src/text_cache/text_cache.h b/src/text_cache/text_cache.h index 0b28bdef..57d66de8 100644 --- a/src/text_cache/text_cache.h +++ b/src/text_cache/text_cache.h @@ -155,84 +155,6 @@ TXT_LangKind; typedef TXT_TokenArray TXT_LangLexFunctionType(Arena *arena, U64 *bytes_processed_counter, String8 string); -//////////////////////////////// -//~ rjf: Cache Types - -typedef struct TXT_Request TXT_Request; -struct TXT_Request -{ - U128 hash; - TXT_LangKind lang; -}; - -typedef struct TXT_RequestNode TXT_RequestNode; -struct TXT_RequestNode -{ - TXT_RequestNode *next; - TXT_Request v; -}; - -typedef struct TXT_Node TXT_Node; -struct TXT_Node -{ - // rjf: links - TXT_Node *next; - TXT_Node *prev; - - // rjf: key - U128 hash; - TXT_LangKind lang; - - // rjf: artifacts - Arena *arena; - TXT_TextInfo info; - - // rjf: metadata - AccessPt access_pt; - B32 is_working; - U64 load_count; -}; - -typedef struct TXT_Slot TXT_Slot; -struct TXT_Slot -{ - TXT_Node *first; - TXT_Node *last; -}; - -//////////////////////////////// -//~ rjf: Shared State - -typedef struct TXT_Shared TXT_Shared; -struct TXT_Shared -{ - Arena *arena; - - // rjf: cache - U64 slots_count; - TXT_Slot *slots; - StripeArray stripes; - TXT_Node **stripes_free_nodes; - - // rjf: requests - Mutex req_mutex; - Arena *req_arena; - TXT_RequestNode *first_req; - TXT_RequestNode *last_req; - U64 req_count; - - // rjf: user -> parse thread - U64 u2p_ring_size; - U8 *u2p_ring_base; - U64 u2p_ring_write_pos; - U64 u2p_ring_read_pos; - CondVar u2p_ring_cv; - Mutex u2p_ring_mutex; - - // rjf: evictor thread - Thread evictor_thread; -}; - //////////////////////////////// //~ rjf: Globals