Commit 33ae4589ea130b42969726510689851e13df580e

Thomas de Grivel 2023-03-27T20:20:27

wip facts_lock

diff --git a/libc3/facts_cursor.c b/libc3/facts_cursor.c
index 14d5b52..2aee28c 100644
--- a/libc3/facts_cursor.c
+++ b/libc3/facts_cursor.c
@@ -96,8 +96,8 @@ s_facts_cursor * facts_cursor_lock_unlock (s_facts_cursor *cursor)
 s_fact * facts_cursor_next (s_facts_cursor *cursor)
 {
   assert(cursor);
-  facts_lock_r(cursor->facts);
   facts_cursor_lock(cursor);
+  facts_lock_r(cursor->facts);
   if (cursor->node) {
     cursor->node = SKIPLIST_NODE_NEXT__fact(cursor->node, 0);
     if (cursor->node &&
@@ -112,8 +112,8 @@ s_fact * facts_cursor_next (s_facts_cursor *cursor)
       *cursor->var_predicate = *fact->predicate;
     if (cursor->var_object)
       *cursor->var_object = *fact->object;
-    facts_cursor_lock_unlock(cursor);
     facts_lock_unlock_r(cursor->facts);
+    facts_cursor_lock_unlock(cursor);
     return fact;
   }
   if (cursor->var_subject)
@@ -122,7 +122,7 @@ s_fact * facts_cursor_next (s_facts_cursor *cursor)
     tag_init_var(cursor->var_predicate);
   if (cursor->var_object)
     tag_init_var(cursor->var_object);
-  facts_cursor_lock_unlock(cursor);
   facts_lock_unlock_r(cursor->facts);
+  facts_cursor_lock_unlock(cursor);
   return NULL;
 }
diff --git a/libc3/facts_with.c b/libc3/facts_with.c
index 8096719..a7c163e 100644
--- a/libc3/facts_with.c
+++ b/libc3/facts_with.c
@@ -11,6 +11,7 @@
  * THIS SOFTWARE.
  */
 #include <assert.h>
+#include <err.h>
 #include <stdlib.h>
 #include "facts_cursor.h"
 #include "facts_spec.h"
@@ -39,6 +40,8 @@ s_facts_with_cursor * facts_with (s_facts *facts,
     cursor->spec = NULL;
   }
   cursor->level = 0;
+  if (pthread_mutex_init(&cursor->mutex, NULL))
+    errx(1, "facts_with: pthread_mutex_init");
   return cursor;
 }
 
diff --git a/libc3/facts_with_cursor.c b/libc3/facts_with_cursor.c
index 11e073a..24abd7c 100644
--- a/libc3/facts_with_cursor.c
+++ b/libc3/facts_with_cursor.c
@@ -33,6 +33,8 @@ void facts_with_cursor_clean (s_facts_with_cursor *cursor)
   }
   free(cursor->levels);
   free(cursor->spec);
+  if (pthread_mutex_destroy(&cursor->mutex))
+    errx(1, "facts_with_cursor_clean: pthread_mutex_destroy");
 }
 
 s_fact * facts_with_cursor_next (s_facts_with_cursor *cursor)
@@ -41,8 +43,10 @@ s_fact * facts_with_cursor_next (s_facts_with_cursor *cursor)
   s_facts_with_cursor_level *level;
   p_facts_spec parent_spec;
   assert(cursor);
+  if (pthread_mutex_lock(&cursor->mutex))
+    errx(1, "facts_with_cursor_next: pthread_mutex_lock");
   if (! cursor->facts_count)
-    return NULL;
+    goto ko;
   if (cursor->level == cursor->facts_count) {
     level = &cursor->levels[cursor->facts_count - 1];
 #ifdef DEBUG_FACTS
@@ -60,14 +64,17 @@ s_fact * facts_with_cursor_next (s_facts_with_cursor *cursor)
     buf_write_1(&g_c3_env.err, "\n");
     buf_flush(&g_c3_env.err);
 #endif
-    if (level->fact)
+    if (level->fact) {
+      if (pthread_mutex_unlock(&cursor->mutex))
+        errx(1, "facts_with_cursor_next: pthread_mutex_unlock");
       return level->fact;
+    }
     free(level->spec);
     level->spec = NULL;
     cursor->level--;
     if (! cursor->level) {
       cursor->facts_count = 0;
-      return NULL;
+      goto ko;
     }
     cursor->level--;
   }
@@ -107,9 +114,15 @@ s_fact * facts_with_cursor_next (s_facts_with_cursor *cursor)
     level->spec = NULL;
     if (! cursor->level) {
       cursor->facts_count = 0;
-      return NULL;
+      goto ko;
     }
     cursor->level--;
   }
+  if (pthread_mutex_unlock(&cursor->mutex))
+    errx(1, "facts_with_cursor_next: pthread_mutex_unlock");
   return fact;
+ ko:
+  if (pthread_mutex_unlock(&cursor->mutex))
+    errx(1, "facts_with_cursor_next: pthread_mutex_unlock");
+  return NULL;
 }
diff --git a/libc3/types.h b/libc3/types.h
index 31caff9..ae98d63 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -456,6 +456,7 @@ struct facts_with_cursor {
   s_facts_with_cursor_level *levels;
   size_t level;
   p_facts_spec spec;
+  pthread_mutex_t mutex;
 };
 
 #endif /* TYPES_H */