2020#include "foundation/log.h"
2121#include "foundation/hash_table.h"
2222#include "foundation/compat.h"
23+ #include "foundation/compat_thread.h"
2324#include "foundation/compat_fs.h"
2425#include "foundation/str_util.h"
2526
@@ -50,6 +51,7 @@ struct cbm_watcher {
5051 cbm_index_fn index_fn ;
5152 void * user_data ;
5253 CBMHashTable * projects ; /* name → project_state_t* */
54+ cbm_mutex_t projects_lock ;
5355 atomic_int stopped ;
5456};
5557
@@ -236,6 +238,7 @@ cbm_watcher_t *cbm_watcher_new(cbm_store_t *store, cbm_index_fn index_fn, void *
236238 w -> index_fn = index_fn ;
237239 w -> user_data = user_data ;
238240 w -> projects = cbm_ht_create (CBM_SZ_32 );
241+ cbm_mutex_init (& w -> projects_lock );
239242 atomic_init (& w -> stopped , 0 );
240243 return w ;
241244}
@@ -244,8 +247,11 @@ void cbm_watcher_free(cbm_watcher_t *w) {
244247 if (!w ) {
245248 return ;
246249 }
250+ cbm_mutex_lock (& w -> projects_lock );
247251 cbm_ht_foreach (w -> projects , free_state_entry , NULL );
248252 cbm_ht_free (w -> projects );
253+ cbm_mutex_unlock (& w -> projects_lock );
254+ cbm_mutex_destroy (& w -> projects_lock );
249255 free (w );
250256}
251257
@@ -264,6 +270,7 @@ void cbm_watcher_watch(cbm_watcher_t *w, const char *project_name, const char *r
264270 }
265271
266272 /* Remove old entry first (key points to state's project_name) */
273+ cbm_mutex_lock (& w -> projects_lock );
267274 project_state_t * old = cbm_ht_get (w -> projects , project_name );
268275 if (old ) {
269276 cbm_ht_delete (w -> projects , project_name );
@@ -272,17 +279,22 @@ void cbm_watcher_watch(cbm_watcher_t *w, const char *project_name, const char *r
272279
273280 project_state_t * s = state_new (project_name , root_path );
274281 cbm_ht_set (w -> projects , s -> project_name , s );
282+ cbm_mutex_unlock (& w -> projects_lock );
275283 cbm_log_info ("watcher.watch" , "project" , project_name , "path" , root_path );
276284}
277285
278286void cbm_watcher_unwatch (cbm_watcher_t * w , const char * project_name ) {
279287 if (!w || !project_name ) {
280288 return ;
281289 }
290+ cbm_mutex_lock (& w -> projects_lock );
282291 project_state_t * s = cbm_ht_get (w -> projects , project_name );
283292 if (s ) {
284293 cbm_ht_delete (w -> projects , project_name );
285294 state_free (s );
295+ }
296+ cbm_mutex_unlock (& w -> projects_lock );
297+ if (s ) {
286298 cbm_log_info ("watcher.unwatch" , "project" , project_name );
287299 }
288300}
@@ -421,7 +433,9 @@ int cbm_watcher_poll_once(cbm_watcher_t *w) {
421433 .now = now_ns (),
422434 .reindexed = 0 ,
423435 };
436+ cbm_mutex_lock (& w -> projects_lock );
424437 cbm_ht_foreach (w -> projects , poll_project , & ctx );
438+ cbm_mutex_unlock (& w -> projects_lock );
425439 return ctx .reindexed ;
426440}
427441
0 commit comments