Re: Multiple instances for embedded prolog interpreter

Jan Wielemaker <[email protected]>
Newsgroups gmane.comp.ai.prolog.swi
Message-ID <[email protected]>
On 07/24/2013 01:37 PM, Stefan Radomski wrote:
> Thank you again for the quick response,
>
> On Jul 23, 2013, at 9:43 PM, Jan Wielemaker <[email protected]>
>   wrote:
>
>> Well, there is a lot of state around. Different engines have their
>> own stacks, but indeed share predicates. If that is the `state' for
>> which you want multiple instances you have two options: create
>> thread_local declared predicates, which are predicates what have
>> their own set of clauses in each thread (which is the same as each
>> engine), or use modules. In each module you can have different sets
>> of predicates that otherwise do not interact as long as you do not
>> tell them to do so.
>
> Let me give you some context here: We are using Prolog as an
> ECMAScript replacement for scripting in XML documents (with good reasons
> :). Our XML interpreter will take a set of such documents and interpret
> them (in fact even a single document might nest others). As such, it is
> imperative that the different Prolog scripting environments from the
> different documents do not interfere with each other.
>
> I can't see thread_local working in our situation as our
> interpreters
> are already multi-threaded and multiple threads are serialized via
> mutexes to linearize access to all of the Prolog interpreter
> (performance is a distant second atm). In the optimal solution, the
> different documents' Prolog environments would behave as if there were
> no others. It *is* working flawlessly if there is only one such document.

Using Prolog from multiple C++ threads is pretty trivial using the
C Prolog engine API.  In any case, if you want to use the thread-local
approach, you must use multiple Prolog engines.  It is a quite ok 
approach, provided you can enumerate the predicates that you will be
using for storing an XML document beforehand, so you can declare all
of them as thread_local.  Possibly a nice benefit is that the clauses
die with the engine (as they are not accessible outside the engine it
makes no sense to keep them).

> I could imagine using the modules approach, but it is important that

Mapping each XML document to a module seems a more natural mapping to me.

> something like the following remains possible and is scoped to the
> current document's environment:
>
> <script>assert(event(foo)).</script>
>
> I am perfectly free to do whatever I want with the Prolog runtime
> before interpreting the contained prolog expression, but the author of
> the XML must not be required to handle the module scoping aspect. I
> tried to prefix every invocation of user supplied prolog with a
> module/1, but did not get it to work:
>
> C++ ---:
> PlCall(("module(ns1)"));
> PlCall("assert(sessionId(a1))");
> PlCall("listing.");
>
> PlCall(("module(ns2)"));
> PlCall("assert(sessionId(a2))");
> PlCall("listing.");
> ---
>
> It seems like asserted facts cannot be scoped in modules as the second listing/0
> will show two sessionId facts:

module/1 sets the module for the toplevel query loop.  You are not 
talking to an interactive toplevel, so that is meaningless.  To insert
in a module, use e.g.,

   PlCall("assert(ns1:sessionId(a2))");

Which is the same as this, which might be a bit handier if you do
not want to look into the term.

   PlCall("ns1:assert(sessionId(a2))");

Note that the C interface allows more explicit interaction with modules.
Most of this is easily added to the C++ interface as well.  If you want
to know what is possible, check out the C API documentation.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.