diff --git a/libc3/env.c b/libc3/env.c
index 83d761d..53b8cf9 100644
--- a/libc3/env.c
+++ b/libc3/env.c
@@ -532,7 +532,7 @@ s_module * env_module_load (s_env *env, s_module *module,
return module;
}
-bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
+bool env_operator_is_right_associative (s_env *env, const s_ident *op)
{
s_facts_with_cursor cursor;
s8 r;
@@ -555,7 +555,7 @@ bool env_operator_is_right_associative (const s_env *env, const s_ident *op)
return r;
}
-s8 env_operator_precedence (const s_env *env, const s_ident *op)
+s8 env_operator_precedence (s_env *env, const s_ident *op)
{
s_facts_with_cursor cursor;
s_tag tag_ident;
diff --git a/libc3/env.h b/libc3/env.h
index 883e9be..0e438ba 100644
--- a/libc3/env.h
+++ b/libc3/env.h
@@ -44,9 +44,9 @@ bool env_eval_progn (s_env *env, const s_list *program,
bool env_eval_tag (s_env *env, const s_tag *tag, s_tag *dest);
s_module * env_module_load (s_env *env, s_module *module,
const s_sym *name, s_facts *facts);
-bool env_operator_is_right_associative (const s_env *env,
+bool env_operator_is_right_associative (s_env *env,
const s_ident *op);
-s8 env_operator_precedence (const s_env *env,
+s8 env_operator_precedence (s_env *env,
const s_ident *op);
/* control structures */
diff --git a/libc3/facts_cursor.c b/libc3/facts_cursor.c
index e438a64..14d5b52 100644
--- a/libc3/facts_cursor.c
+++ b/libc3/facts_cursor.c
@@ -13,12 +13,20 @@
#include <assert.h>
#include <err.h>
#include <stdlib.h>
+#include "facts.h"
#include "facts_cursor.h"
#include "skiplist__fact.h"
#include "skiplist_node__fact.h"
#include "tag.h"
-s_facts_cursor * facts_cursor_init (s_facts_cursor *cursor,
+void facts_cursor_clean (s_facts_cursor *cursor)
+{
+ assert(cursor);
+ facts_cursor_lock_clean(cursor);
+}
+
+s_facts_cursor * facts_cursor_init (s_facts *facts,
+ s_facts_cursor *cursor,
s_skiplist__fact *index,
s_fact *start,
s_fact *end)
@@ -48,12 +56,48 @@ s_facts_cursor * facts_cursor_init (s_facts_cursor *cursor,
cursor->var_subject = NULL;
cursor->var_predicate = NULL;
cursor->var_object = NULL;
+ cursor->facts = facts;
+ facts_cursor_lock_init(cursor);
+ return cursor;
+}
+
+s_facts_cursor * facts_cursor_lock (s_facts_cursor *cursor)
+{
+ assert(cursor);
+ if (pthread_mutex_lock(&cursor->mutex))
+ errx(1, "facts_cursor_lock: pthread_mutex_lock");
+ return cursor;
+}
+
+s_facts_cursor * facts_cursor_lock_clean (s_facts_cursor *cursor)
+{
+ assert(cursor);
+ if (pthread_mutex_destroy(&cursor->mutex))
+ errx(1, "facts_cursor_lock_clean: pthread_mutex_destroy");
+ return cursor;
+}
+
+s_facts_cursor * facts_cursor_lock_init (s_facts_cursor *cursor)
+{
+ assert(cursor);
+ if (pthread_mutex_init(&cursor->mutex, NULL))
+ errx(1, "facts_cursor_lock_init: pthread_mutex_init");
+ return cursor;
+}
+
+s_facts_cursor * facts_cursor_lock_unlock (s_facts_cursor *cursor)
+{
+ assert(cursor);
+ if (pthread_mutex_unlock(&cursor->mutex))
+ errx(1, "facts_cursor_lock_unlock: pthread_mutex_unlock");
return cursor;
}
s_fact * facts_cursor_next (s_facts_cursor *cursor)
{
assert(cursor);
+ facts_lock_r(cursor->facts);
+ facts_cursor_lock(cursor);
if (cursor->node) {
cursor->node = SKIPLIST_NODE_NEXT__fact(cursor->node, 0);
if (cursor->node &&
@@ -68,6 +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);
return fact;
}
if (cursor->var_subject)
@@ -76,5 +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);
return NULL;
}
diff --git a/libc3/facts_cursor.h b/libc3/facts_cursor.h
index f08ba0f..91ae855 100644
--- a/libc3/facts_cursor.h
+++ b/libc3/facts_cursor.h
@@ -16,12 +16,18 @@
#include "types.h"
/* Stack allocation compatible functions */
-s_facts_cursor * facts_cursor_init (s_facts_cursor *cursor,
+void facts_cursor_clean (s_facts_cursor *cursor);
+s_facts_cursor * facts_cursor_init (s_facts *facts,
+ s_facts_cursor *cursor,
s_skiplist__fact *tree,
s_fact *start,
s_fact *end);
/* Modifiers */
-s_fact * facts_cursor_next (s_facts_cursor *cursor);
+s_facts_cursor * facts_cursor_lock (s_facts_cursor *cursor);
+s_facts_cursor * facts_cursor_lock_clean (s_facts_cursor *cursor);
+s_facts_cursor * facts_cursor_lock_init (s_facts_cursor *cursor);
+s_facts_cursor * facts_cursor_lock_unlock (s_facts_cursor *cursor);
+s_fact * facts_cursor_next (s_facts_cursor *cursor);
#endif /* FACTS_H */
diff --git a/libc3/facts_with.c b/libc3/facts_with.c
index ca3704b..8096719 100644
--- a/libc3/facts_with.c
+++ b/libc3/facts_with.c
@@ -17,7 +17,7 @@
#include "facts_with.h"
#include "tag.h"
-s_facts_with_cursor * facts_with (const s_facts *facts,
+s_facts_with_cursor * facts_with (s_facts *facts,
s_facts_with_cursor *cursor,
p_facts_spec spec)
{
@@ -42,7 +42,7 @@ s_facts_with_cursor * facts_with (const s_facts *facts,
return cursor;
}
-s_facts_cursor * facts_with_0 (const s_facts *facts,
+s_facts_cursor * facts_with_0 (s_facts *facts,
s_facts_cursor *cursor,
s_tag *var_subject,
s_tag *var_predicate,
@@ -50,14 +50,14 @@ s_facts_cursor * facts_with_0 (const s_facts *facts,
{
assert(facts);
assert(cursor);
- facts_cursor_init(cursor, facts->index_spo, NULL, NULL);
+ facts_cursor_init(facts, cursor, facts->index_spo, NULL, NULL);
cursor->var_subject = var_subject;
cursor->var_predicate = var_predicate;
cursor->var_object = var_object;
return cursor;
}
-s_facts_cursor * facts_with_1_2 (const s_facts *facts,
+s_facts_cursor * facts_with_1_2 (s_facts *facts,
s_facts_cursor *cursor,
const s_tag *subject,
const s_tag *predicate,
@@ -87,14 +87,14 @@ s_facts_cursor * facts_with_1_2 (const s_facts *facts,
tree = facts->index_pos;
else
tree = facts->index_osp;
- facts_cursor_init(cursor, tree, &start, &end);
+ facts_cursor_init(facts, cursor, tree, &start, &end);
cursor->var_subject = var_subject;
cursor->var_predicate = var_predicate;
cursor->var_object = var_object;
return cursor;
}
-s_facts_cursor * facts_with_3 (const s_facts *facts,
+s_facts_cursor * facts_with_3 (s_facts *facts,
s_facts_cursor *cursor,
const s_tag *subject,
const s_tag *predicate,
@@ -109,10 +109,10 @@ s_facts_cursor * facts_with_3 (const s_facts *facts,
fact.subject = subject;
fact.predicate = predicate;
fact.object = object;
- return facts_cursor_init(cursor, facts->index_spo, &fact, &fact);
+ return facts_cursor_init(facts, cursor, facts->index_spo, &fact, &fact);
}
-s_facts_cursor * facts_with_tags (const s_facts *facts,
+s_facts_cursor * facts_with_tags (s_facts *facts,
s_facts_cursor *cursor,
s_tag *subject,
s_tag *predicate,
diff --git a/libc3/facts_with.h b/libc3/facts_with.h
index e9bac77..f684827 100644
--- a/libc3/facts_with.h
+++ b/libc3/facts_with.h
@@ -15,17 +15,17 @@
#include "types.h"
-s_facts_with_cursor * facts_with (const s_facts *facts,
+s_facts_with_cursor * facts_with (s_facts *facts,
s_facts_with_cursor *cursor,
p_facts_spec spec);
-s_facts_cursor * facts_with_0 (const s_facts *facts,
+s_facts_cursor * facts_with_0 (s_facts *facts,
s_facts_cursor *cursor,
s_tag *var_subject,
s_tag *var_predicate,
s_tag *var_object);
-s_facts_cursor * facts_with_1_2 (const s_facts *facts,
+s_facts_cursor * facts_with_1_2 (s_facts *facts,
s_facts_cursor *cursor,
const s_tag *subject,
const s_tag *predicate,
@@ -34,13 +34,13 @@ s_facts_cursor * facts_with_1_2 (const s_facts *facts,
s_tag *var_predicate,
s_tag *var_object);
-s_facts_cursor * facts_with_3 (const s_facts *facts,
+s_facts_cursor * facts_with_3 (s_facts *facts,
s_facts_cursor *cursor,
const s_tag *subject,
const s_tag *predicate,
const s_tag *object);
-s_facts_cursor * facts_with_tags (const s_facts *facts,
+s_facts_cursor * facts_with_tags (s_facts *facts,
s_facts_cursor *cursor,
s_tag *subject,
s_tag *predicate,
diff --git a/libc3/facts_with_cursor.c b/libc3/facts_with_cursor.c
index 3220d9b..11e073a 100644
--- a/libc3/facts_with_cursor.c
+++ b/libc3/facts_with_cursor.c
@@ -25,7 +25,10 @@ void facts_with_cursor_clean (s_facts_with_cursor *cursor)
uw i = 0;
assert(cursor);
while (i < cursor->facts_count) {
- free(cursor->levels[i].spec);
+ if (cursor->levels[i].spec) {
+ free(cursor->levels[i].spec);
+ facts_cursor_clean(&cursor->levels[i].cursor);
+ }
i++;
}
free(cursor->levels);
diff --git a/libc3/types.h b/libc3/types.h
index 20a2956..31caff9 100644
--- a/libc3/types.h
+++ b/libc3/types.h
@@ -416,6 +416,7 @@ struct facts {
};
struct facts_cursor {
+ s_facts *facts;
s_skiplist__fact *index;
s_skiplist_node__fact *node;
s_fact start;
@@ -423,6 +424,7 @@ struct facts_cursor {
s_tag *var_subject;
s_tag *var_predicate;
s_tag *var_object;
+ pthread_mutex_t mutex;
};
/* 6 */
@@ -448,7 +450,7 @@ struct facts_with_cursor_level {
/* 7 */
struct facts_with_cursor {
- const s_facts *facts;
+ s_facts *facts;
s_binding *bindings;
size_t facts_count;
s_facts_with_cursor_level *levels;
diff --git a/test/facts_cursor_test.c b/test/facts_cursor_test.c
index f182a8f..7531ac0 100644
--- a/test/facts_cursor_test.c
+++ b/test/facts_cursor_test.c
@@ -64,30 +64,42 @@ void facts_cursor_test_init ()
facts_add_fact(&facts, fact + i);
i++;
}
- TEST_EQ(facts_cursor_init(&cursor, facts.index_spo, NULL, NULL),
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_spo, NULL, NULL),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_pos, NULL, NULL),
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_pos, NULL, NULL),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_osp, NULL, NULL),
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_osp, NULL, NULL),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_spo, fact, fact),
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_spo, fact, fact),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_pos, fact, fact),
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_pos, fact, fact),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_osp, fact, fact),
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_osp, fact, fact),
&cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_spo, fact + 1,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_spo, fact + 1,
fact + 1), &cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_pos, fact + 1,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_pos, fact + 1,
fact + 1), &cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_osp, fact + 1,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_osp, fact + 1,
fact + 1), &cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_spo, fact,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_spo, fact,
fact + 6), &cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_pos, fact,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_pos, fact,
fact + 6), &cursor);
- TEST_EQ(facts_cursor_init(&cursor, facts.index_osp, fact,
+ facts_cursor_clean(&cursor);
+ TEST_EQ(facts_cursor_init(&facts, &cursor, facts.index_osp, fact,
fact + 6), &cursor);
+ facts_cursor_clean(&cursor);
i = 0;
while (p[i]) {
fact_test_clean_1(fact + i);
@@ -134,46 +146,55 @@ void facts_cursor_test_next ()
facts_add_fact(&facts, fact + i);
i++;
}
- facts_cursor_init(&cursor, facts.index_spo, NULL, NULL);
+ facts_cursor_init(&facts, &cursor, facts.index_spo, NULL, NULL);
i = 0;
while (p[i]) {
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + i);
i++;
}
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_pos, NULL, NULL);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_pos, NULL, NULL);
i = 0;
while (p[i]) {
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + i);
i++;
}
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_osp, NULL, NULL);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_osp, NULL, NULL);
i = 0;
while (p[i]) {
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + i);
i++;
}
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_spo, fact, fact);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_spo, fact, fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_pos, fact, fact);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_pos, fact, fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_osp, fact, fact);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_osp, fact, fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_spo, fact + 1, fact + 1);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_spo, fact + 1, fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_pos, fact + 1, fact + 1);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_pos, fact + 1, fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_osp, fact + 1, fact + 1);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_osp, fact + 1, fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_spo, fact, fact + 6);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_spo, fact, fact + 6);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 2);
@@ -182,7 +203,8 @@ void facts_cursor_test_next ()
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 5);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 6);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_pos, fact, fact + 6);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_pos, fact, fact + 6);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 2);
@@ -191,7 +213,8 @@ void facts_cursor_test_next ()
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 5);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 6);
TEST_EQ(facts_cursor_next(&cursor), NULL);
- facts_cursor_init(&cursor, facts.index_osp, fact, fact + 6);
+ facts_cursor_clean(&cursor);
+ facts_cursor_init(&facts, &cursor, facts.index_osp, fact, fact + 6);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 1);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 2);
@@ -200,6 +223,7 @@ void facts_cursor_test_next ()
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 5);
FACT_TEST_EQ(facts_cursor_next(&cursor), fact + 6);
TEST_EQ(facts_cursor_next(&cursor), NULL);
+ facts_cursor_clean(&cursor);
i = 0;
while (p[i]) {
fact_test_clean_1(fact + i);