With reference to issue #120 (#120), The following solution mentioned in issue #3 was implemented for it.
pyswip doesn't support multithreading at all. IMHO, contemporary API (or at least pyswip.prolog module) needs to be redesigned from the scratch, see: http://www.swi-prolog.org/pldoc/man?section=foreignthread
I've devised an ad-hoc non-intrusive solution, just to test things out:
import pyswip, ctypes
class PrologMT(pyswip.Prolog):
"""Multi-threaded (one-to-one) pyswip.Prolog ad-hoc reimpl"""
_swipl = pyswip.core._lib
PL_thread_self = _swipl.PL_thread_self
PL_thread_self.restype = ctypes.c_int
PL_thread_attach_engine = _swipl.PL_thread_attach_engine
PL_thread_attach_engine.argtypes = [ctypes.c_void_p]
PL_thread_attach_engine.restype = ctypes.c_int
@classmethod
def _init_prolog_thread(cls):
pengine_id = cls.PL_thread_self()
if (pengine_id == -1):
pengine_id = cls.PL_thread_attach_engine(None)
print("{INFO} attach pengine to thread: %d" % pengine_id)
if (pengine_id == -1):
raise pyswip.prolog.PrologError("Unable to attach new Prolog engine to the thread")
elif (pengine_id == -2):
print("{WARN} Single-threaded swipl build, beware!")
class _QueryWrapper(pyswip.Prolog._QueryWrapper):
def __call__(self, *args, **kwargs):
PrologMT._init_prolog_thread()
return super().__call__(*args, **kwargs)
PrologMT is a drop-in replacement for pyswip.Prolog in your code. On each query, native thread's local storage is scanned for the prolog engine (PL_thread_self). If there is no pengine associated with the current thread, new one will be created (PL_thread_attach_engine), without any further resource management.
You couldn't use any term_t-related functions of libswipl from the thread with no pengine - that leads to SEGFAULT. By default, the thread which imports pyswip first, will be implicitly associated with the single ("main") pengine, as PL_initialise is called on the pyswip.prolog module top-level.
Originally posted by @xpinguin in #3 (comment)
Multithreading was possible after the suggested solution. However, I receive a NestedQueryError("The last query was not closed") exception whenever multiple threads try to perform the "query" operation. So is there any inherent "Queue" mechanism involved for "query" operations to avoid the above error? If not, kindly suggest some other solution for the same.
With reference to issue #120 (#120), The following solution mentioned in issue #3 was implemented for it.
pyswipdoesn't support multithreading at all. IMHO, contemporary API (or at leastpyswip.prologmodule) needs to be redesigned from the scratch, see: http://www.swi-prolog.org/pldoc/man?section=foreignthreadI've devised an ad-hoc non-intrusive solution, just to test things out:
PrologMTis a drop-in replacement forpyswip.Prologin your code. On each query, native thread's local storage is scanned for the prolog engine (PL_thread_self). If there is no pengine associated with the current thread, new one will be created (PL_thread_attach_engine), without any further resource management.You couldn't use any
term_t-related functions oflibswiplfrom the thread with no pengine - that leads to SEGFAULT. By default, the thread which importspyswipfirst, will be implicitly associated with the single ("main") pengine, asPL_initialiseis called on thepyswip.prologmodule top-level.Originally posted by @xpinguin in #3 (comment)
Multithreading was possible after the suggested solution. However, I receive a NestedQueryError("The last query was not closed") exception whenever multiple threads try to perform the "query" operation. So is there any inherent "Queue" mechanism involved for "query" operations to avoid the above error? If not, kindly suggest some other solution for the same.