[m-rev.] for review: [PATCH 1/4] Add thread_safe attribute to store procedures.

Peter Wang novalazy at gmail.com
Tue Jul 22 15:00:23 AEST 2014


The mutvar procedures are not truly thread-safe but neither does
obtaining a global lock make them become thread-safe in a useful way,
except perhaps avoiding data races.  On the other hand, the global lock
inhibits parallelism in programs that do use mutvars in a thread-safe
manner.

library/store.m:
	As above.
---
 library/store.m | 94 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 47 insertions(+), 47 deletions(-)

diff --git a/library/store.m b/library/store.m
index a25e65a..bd93905 100644
--- a/library/store.m
+++ b/library/store.m
@@ -281,25 +281,25 @@ store.init(S) :-
 
 :- pragma foreign_proc("C",
     store.do_init(_S0::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     TypeInfo_for_S = 0;
 ").
 :- pragma foreign_proc("C#",
     store.do_init(_S0::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     TypeInfo_for_S = null;
 ").
 :- pragma foreign_proc("Java",
     store.do_init(_S0::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     TypeInfo_for_S = null;
 ").
 :- pragma foreign_proc("Erlang",
     store.do_init(_S0::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     TypeInfo_for_S = 'XXX'
 ").
@@ -321,7 +321,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("C",
     new_mutvar(Val::in, Mutvar::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     MR_offset_incr_hp_msg(Mutvar, MR_SIZE_SLOT_SIZE, MR_SIZE_SLOT_SIZE + 1,
         MR_ALLOC_ID, ""store.mutvar/2"");
@@ -332,7 +332,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("C",
     get_mutvar(Mutvar::in, Val::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     Val = * (MR_Word *) Mutvar;
     S = S0;
@@ -340,7 +340,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("C",
     set_mutvar(Mutvar::in, Val::in, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     * (MR_Word *) Mutvar = Val;
     S = S0;
@@ -350,21 +350,21 @@ store.init(S) :-
 
 :- pragma foreign_proc("C#",
     new_mutvar(Val::in, Mutvar::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar = new object[] { Val };
 ").
 
 :- pragma foreign_proc("C#",
     get_mutvar(Mutvar::in, Val::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Mutvar[0];
 ").
 
 :- pragma foreign_proc("C#",
     set_mutvar(Mutvar::in, Val::in, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar[0] = Val;
 ").
@@ -373,21 +373,21 @@ store.init(S) :-
 
 :- pragma foreign_proc("Java",
     new_mutvar(Val::in, Mutvar::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar = new mutvar.Mutvar(Val);
 ").
 
 :- pragma foreign_proc("Java",
     get_mutvar(Mutvar::in, Val::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Mutvar.object;
 ").
 
 :- pragma foreign_proc("Java",
     set_mutvar(Mutvar::in, Val::in, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar.object = Val;
 ").
@@ -399,7 +399,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("Erlang",
     new_mutvar(Val::in, Mutvar::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar = ets:new(mutvar, [set, public]),
     ets:insert(Mutvar, {value, Val}),
@@ -408,7 +408,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("Erlang",
     get_mutvar(Mutvar::in, Val::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     [{value, Val}] = ets:lookup(Mutvar, value),
     S = S0
@@ -416,7 +416,7 @@ store.init(S) :-
 
 :- pragma foreign_proc("Erlang",
     set_mutvar(Mutvar::in, Val::in, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     ets:insert(Mutvar, {value, Val}),
     S = S0
@@ -431,7 +431,7 @@ copy_mutvar(Mutvar, Copy, !S) :-
 
 :- pragma foreign_proc("C",
     unsafe_new_uninitialized_mutvar(Mutvar::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     MR_offset_incr_hp_msg(Mutvar, MR_SIZE_SLOT_SIZE, MR_SIZE_SLOT_SIZE + 1,
         MR_ALLOC_ID, ""store.mutvar/2"");
@@ -441,14 +441,14 @@ copy_mutvar(Mutvar, Copy, !S) :-
 
 :- pragma foreign_proc("C#",
     unsafe_new_uninitialized_mutvar(Mutvar::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar = new object[1];
 ").
 
 :- pragma foreign_proc("Java",
     unsafe_new_uninitialized_mutvar(Mutvar::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Mutvar = new mutvar.Mutvar();
 ").
@@ -588,7 +588,7 @@ store.new_cyclic_mutvar(Func, MutVar, !Store) :-
 
 :- pragma foreign_proc("C",
     new_ref(Val::di, Ref::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     MR_offset_incr_hp_msg(Ref, MR_SIZE_SLOT_SIZE, MR_SIZE_SLOT_SIZE + 1,
         MR_ALLOC_ID, ""store.ref/2"");
@@ -599,21 +599,21 @@ store.new_cyclic_mutvar(Func, MutVar, !Store) :-
 
 :- pragma foreign_proc("C#",
     new_ref(Val::di, Ref::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref = new store.Ref(Val);
 ").
 
 :- pragma foreign_proc("Java",
     new_ref(Val::di, Ref::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref = new store.Ref(Val);
 ").
 
 :- pragma foreign_proc("Erlang",
     new_ref(Val::di, Ref::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref = ets:new(mutvar, [set, public]),
     ets:insert(Ref, {value, Val}),
@@ -633,7 +633,7 @@ copy_ref_value(Ref, Val) -->
 
 :- pragma foreign_proc("C",
     unsafe_ref_value(Ref::in, Val::uo, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, will_not_modify_trail],
+    [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail],
 "
     Val = * (MR_Word *) Ref;
     S = S0;
@@ -641,21 +641,21 @@ copy_ref_value(Ref, Val) -->
 
 :- pragma foreign_proc("C#",
     unsafe_ref_value(Ref::in, Val::uo, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Ref.getValue();
 ").
 
 :- pragma foreign_proc("Java",
     unsafe_ref_value(Ref::in, Val::uo, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Ref.getValue();
 ").
 
 :- pragma foreign_proc("Erlang",
     unsafe_ref_value(Ref::in, Val::uo, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     [{value, Val}] = ets:lookup(Ref, value),
     S = S0
@@ -675,7 +675,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C",
     arg_ref(Ref::in, ArgNum::in, ArgRef::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, may_not_duplicate],
+    [will_not_call_mercury, promise_pure, thread_safe, may_not_duplicate],
 "{
     MR_TypeInfo         type_info;
     MR_TypeInfo         arg_type_info;
@@ -715,7 +715,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C#",
     arg_ref(Ref::in, ArgNum::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     /*
     ** XXX Some dynamic type-checking should be done here to check that
@@ -728,7 +728,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("Java",
     arg_ref(Ref::in, ArgNum::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     /*
     ** XXX Some dynamic type-checking should be done here to check that
@@ -741,7 +741,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C",
     new_arg_ref(Val::di, ArgNum::in, ArgRef::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure, may_not_duplicate],
+    [will_not_call_mercury, promise_pure, thread_safe, may_not_duplicate],
 "{
     MR_TypeInfo         type_info;
     MR_TypeInfo         arg_type_info;
@@ -793,7 +793,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C#",
     new_arg_ref(Val::di, ArgNum::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     /*
     ** XXX Some dynamic type-checking should be done here to check that
@@ -806,7 +806,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("Java",
     new_arg_ref(Val::di, ArgNum::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     /*
     ** XXX Some dynamic type-checking should be done here to check that
@@ -819,7 +819,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C",
     set_ref(Ref::in, ValRef::in, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     * (MR_Word *) Ref = * (MR_Word *) ValRef;
     S = S0;
@@ -827,21 +827,21 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C#",
     set_ref(Ref::in, ValRef::in, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref.setValue(ValRef.getValue());
 ").
 
 :- pragma foreign_proc("Java",
     set_ref(Ref::in, ValRef::in, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref.setValue(ValRef.getValue());
 ").
 
 :- pragma foreign_proc("C",
     set_ref_value(Ref::in, Val::di, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     * (MR_Word *) Ref = Val;
     S = S0;
@@ -849,28 +849,28 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("Java",
     set_ref_value(Ref::in, Val::di, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Ref.setValue(Val);
 ").
 
 :- pragma foreign_proc("C",
     extract_ref_value(_S::di, Ref::in, Val::out),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = * (MR_Word *) Ref;
 ").
 
 :- pragma foreign_proc("C#",
     extract_ref_value(_S::di, Ref::in, Val::out),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Ref.getValue();
 ").
 
 :- pragma foreign_proc("Java",
     extract_ref_value(_S::di, Ref::in, Val::out),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     Val = Ref.getValue();
 ").
@@ -879,7 +879,7 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C",
     unsafe_arg_ref(Ref::in, Arg::in, ArgRef::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "{
     /* unsafe - does not check type & arity, won't handle no_tag types */
     MR_Word *Ptr;
@@ -891,21 +891,21 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C#",
     unsafe_arg_ref(Ref::in, Arg::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     ArgRef = new store.Ref(Ref.getValue(), Arg);
 ").
 
 :- pragma foreign_proc("Java",
     unsafe_arg_ref(Ref::in, Arg::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     ArgRef = new store.Ref(Ref.getValue(), Arg);
 ").
 
 :- pragma foreign_proc("C",
     unsafe_new_arg_ref(Val::di, Arg::in, ArgRef::out, S0::di, S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "{
     /* unsafe - does not check type & arity, won't handle no_tag types */
     MR_Word *Ptr;
@@ -917,14 +917,14 @@ ref_functor(Ref, Functor, Arity, !Store) :-
 
 :- pragma foreign_proc("C#",
     unsafe_new_arg_ref(Val::di, Arg::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     ArgRef = new store.Ref(Val, Arg);
 ").
 
 :- pragma foreign_proc("Java",
     unsafe_new_arg_ref(Val::di, Arg::in, ArgRef::out, _S0::di, _S::uo),
-    [will_not_call_mercury, promise_pure],
+    [will_not_call_mercury, promise_pure, thread_safe],
 "
     ArgRef = new store.Ref(Val, Arg);
 ").
-- 
1.8.4




More information about the reviews mailing list