Open ghost opened 4 years ago
JPL now aims to support multi threads (with much help from Jan), although it didn't originally, and I didn't review the (various) caching :-/
Couldn't we mutex just the jpl_assert? or am I missing something.
Also, any caching was speculative, and not demonstrably compute-saving...
Yeah, I guess this would be also a form of caching:
jpl_object_to_type(Ref, Type) :-
jpl_is_object(Ref),
( jpl_iref_type_cache(Ref, T)
-> true % T is Tag's type
; jpl_object_to_class(Ref, Cobj), % else get ref to class obj
jpl_class_to_type(Cobj, T), % get type of class it denotes
with_mutex(jpl_iref_type_cache_mutex,
(retractall(jpl_iref_type_cache(Ref,_)),
assertz(jpl_iref_type_cache(Ref,T)))
)
),
Type = T.
In the above a race condition might appear that two or more threads calculate T, but in the end there will be only one entry. I am using retractall/1 to remove a previous entry. You
could also use a if-then-else check instead, i.e. a conditional asssertz/1. As long as there is a mutex, the thread will have the critical section exclusively, and can determine whether it
needs to add a cache entry or not. Problem is how to box it
into a meta call jpl_assert/1
or better jpl_update/1
. You need
to know what are the primary key arguments and what are the
data arguments of the item you want to update.
This issue has been mentioned on SWI-Prolog. There might be relevant details there:
https://swi-prolog.discourse.group/t/global-variables-and-threads/2519/5
Is JPL supposed to be multi-threaded capabel, i.e. reentrant? Because this code doesn’t work as a cache: There might be race conditions where two or more jpl_iref_type_cache/2 are asserted. A reentrant cache is a little bit more difficult to implement and needs a mutex.
One way to do it, is as follows. But it has the drawback that time is spent inside the mutx by ‘jpl_object_to_class/2’ etc… Using destructive operations which would be also seen through facts, this can be even done outside of the mutex, and would be faster. So this is only an imperfect sketch:
Maybe alternatively an elegant approach could be using SWI-Prolog shared tabling.