43.3.3 Another Multi Threaded Example (Prolog Top Level)

This is another multi threaded version of the train example (see Train Example).

In this example prolog is the toplevel and Java is invoked via library(jasper).

// MultiSimple2.java
import se.sics.jasper.Jasper; import se.sics.jasper.Query; import se.sics.jasper.Prolog; import se.sics.jasper.SICStus; import java.util.ArrayList; import java.util.HashMap; import java.util.ListIterator; public class MultiSimple2 { class Client extends Thread { Prolog jp; SICStus sp; String qs; Client(Prolog p, SICStus s, String queryString) { jp = p; sp = s; qs = queryString; } public void run() { HashMap WayMap = new HashMap(); try { synchronized(jp) { Query query = jp.openPrologQuery(qs, WayMap); try { while (query.nextSolution()) { System.out.println(WayMap); } } finally { query.close(); } } } catch ( Exception e ) { e.printStackTrace(); } } } class Watcher extends Thread { SICStus mySp; ArrayList threadList = new ArrayList(2); public boolean add(Client cl) { return threadList.add((Object)cl); } boolean at_least_one_is_alive(ArrayList tl) { ListIterator li = tl.listIterator(); boolean f = false; while (li.hasNext()) { boolean alive = ((Client)(li.next())).isAlive(); f = f || alive; } return f; } public void run() { while (at_least_one_is_alive(threadList)) { try { this.sleep(1000); } catch (InterruptedException ie) { System.err.println("Watcher interrupted."); } } mySp.stopServer(); } Watcher(SICStus sp) { mySp = sp; } } public void CallBack() { try { SICStus sp = SICStus.getCaller(); // get the SICStus object sp.load("train.ql"); Prolog jp = sp.newProlog(); // Create a new Prolog Interface Client c1 = new Client(jp, sp, "connected('Írebro', 'Hallsberg', Way1, Way1)."); c1.start(); // The prolog variable names in the Map are different from above so // we can tell which query gives what solution. Client c2 = new Client(jp, sp, "connected('Stockholm', 'Hallsberg', Way2, Way2)."); c2.start(); Watcher w = new Watcher(sp); w.add(c1); w.add(c2); w.start(); sp.startServer(); // And finally start the server. This // method call does not return until // some other thread calls sp.stopServer(). } catch ( Exception e ) { e.printStackTrace(); } } }
% multisimple2.pl
:- use_module(library(jasper)). main:- jasper_initialize(JVM), jasper_new_object(JVM, 'MultiSimple2', init, init, Obj), jasper_call(JVM, method('', 'CallBack', [instance]), 'CallBack'(+object('')), 'CallBack'(Obj)).
  1. This example is similar to the previous multi threaded example See Multi Threaded Example, but in this case Prolog is the top level.
  2. Since a SICStus object already exists when the java method CallBack is called, we cannot use Jasper.newProlog to obtain a Prolog interface. Instead we can use the SICStus method getCaller to get a handle on the SICStus object.
  3. In this example we cannot use the restore method to load the prolog saved state, since it unloads all foreign resources. This includes library(jasper) from which the call to Java was made. Instead the method SICStus.load can be used to load a compiled prolog file. See the HTML Jasper documentation for details on this method. See Load Predicates, for how to create a `.ql' file.
  4. The rest of the example is similar to the previous multi threaded example with the addition of a watcher class, which is used to monitor the client threads. This is necessary if the method startServer is to return. See the HTML Jasper documentation on the methods SICStus.startServer and SICStus.stopServer.