@c -*-texinfo-*-
@node IC-PrologII, References, ReferenceManual, Top
@chapter Interface with IC-Prolog II

This chapter describes the extra primitives available when Parlog is
run under the IC-Prolog II system.  These primitives are not available
in the standalone Parlog system.

In IC-Prolog II, a thread is a
sequential Prolog process.  IC-Prolog II is a multi-threaded system so
there may be more than one thread running concurrently.

@menu
* CallingProlog::               Parlog calling Prolog
* PipeCommunication::           Inter thread/process communication
* NetworkCommunication::        TCP/IP and Mailboxes
* Other::                       Miscellaneous Additional Primitives
@end menu

@node CallingProlog, PipeCommunication,  , IC-PrologII
@section Calling Prolog

To enable Parlog to call Prolog, there is a suite of Parlog primitives
which execute Prolog goals.  This is achieved by executing the Prolog
goals in separate threads in the multi-threaded IC-Prolog II system.

There is more than one such primitive because the goal may be executed
in a new thread or an existing server thread, the goal may produce
one or more solutions which can be generated eagerly or lazily, and
we may or may not be interested in the answer bindings.

@table @code
@item prolog_cmd(G)
@findex prolog_cmd/1
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} A new thread is created to execute the Prolog goal G.
G is a command
so no results are expected back to Parlog i.e. any variables
in G will not be bound.

@item prolog(G)
@findex prolog/1
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} A new thread is created to execute the Prolog goal G. 
Variables in G will be bound to Prolog's first solution and
the values communicated back to Parlog.

@item prolog(G,P)
@findex prolog/2
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} A new thread is created to execute the Prolog goal G.
All the solutions of
G will be available by successively reading from the port P
using @code{read_pipe/2}.  When there
are no more solutions, reading from port P will return @code{end_of_file}.

@item prolog(G,P,Th)
@findex prolog/3
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} Same as @code{prolog/2} with the extra argument returning
the thread ID of the newly created thread.

@item lazy_prolog(G,P,Th)
@findex lazy_prolog/3
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} Same as @code{prolog/3} except that the solutions are
generated lazily and it is the programmer's responsibility to get the
next solution by explicitly resuming the suspended Prolog thread by
calling @code{resume(Th)}.

@item qprolog(G)
@findex qprolog/1
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} Similar to @code{prolog/1} but quicker to execute since
it uses the background Prolog server thread instead of creating a new
thread.  Note that G should be a simple query only since long queries
will monopolise the Prolog server and cause a bottleneck.

@item resume(Th)
@findex resume/1
@dfn{synchronisation:} Suspends until Th is instantiated.

@dfn{behaviour:} Resume execution of the specified thread.
This is used to wake up explicitly suspended Prolog threads.
If Th is 0, the next runnable thread is resumed.
@code{resume/1} returns an error if Th is not a currently valid
thread.

@item kill_thread(Th)
@findex kill_thread/1
@dfn{synchronisation:} Suspends until Th is instantiated.

@dfn{behaviour:} Kills the specified thread and reclaims the memory space.
@end table

@node PipeCommunication, NetworkCommunication, CallingProlog, IC-PrologII
@section Pipe Communication

In the description below, a pipe is a communication channel between two
threads or processes.  A pipe has two end which are called ports.  An output
port is where terms enter the pipe (i.e. written out by a thread), and an
input port is where the terms leave the pipe (i.e. read in by a thread).
The same mechanism can be used for Prolog to Prolog, Parlog to Parlog,
Prolog to Parlog or Parlog to Prolog communication.

@table @code
@item pipe(OP,IP)
@findex pipe/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Creates a new pipe and binds OP to the output end and IP to
the input end of the pipe.  Terms which are written to OP may be
read from IP.  The structure of a port term is
@code{port(N)} where N is an integer.

@item write_pipe(OP,T)
@findex write_pipe/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Outputs the term T to the output port OP.  OP must be an
output port owned by the current thread, otherwise the primitive fails.
Ownership of a port is automatically set to the current thread if there is no
current owner.  Note that creation of a pipe does not set ownership for the
ports.  Thus a pipe may be created by one thread and used by another thread.
If any thread is suspended on a read, @code{write_pipe/2} wakes it after
T is written out to the pipe.

@item look_pipe(IP,T)
@findex look_pipe/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Copies a term T from the input port IP.  The term is not removed
from the pipe.  IP must be an input port owned by the current thread,
otherwise the primitive fails.  Ownership of a port is automatically set to
the current thread if there is no current owner.  The pipe is `locked' before
the term is read.  This is to prevent multiple readers accessing the pipe
simultaneously.  The lock is not released by this primitive (see
@code{commit_read/1}).  @code{look_pipe/2} suspends if the port is
already locked or if the pipe is empty.  If the output port of the pipe is
closed, @code{look_pipe/2} binds T to the constant @code{end_of_file}.

@item commit_read(IP)
@findex commit_read/1
@dfn{synchronisation:} Suspends until IP is instantiated.

@dfn{behaviour:} Removes the term previously read by @code{look_pipe/2}
from the pipe and unlock the pipe.  IP must be an input port
owned by the current thread, otherwise the primitive fails.
@code{commit_read/1} fails if the pipe is not locked (i.e. no previous
@code{look_pipe/2}).

@item read_pipe(IP,T)
@findex read_pipe/2
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Reads a term T from the input port IP.  Semantically, this is
equivalent to @code{look_pipe(IP,T)} followed sequentially by
@code{commit_read(IP)}.

@item empty_pipe(IP)
@findex empty_pipe/1
@dfn{synchronisation:} Suspends until IP is instantiated.

@dfn{behaviour:} Succeeds if there is no data ready to be read from input port IP.

@item is_iport(Port)
@findex is_iport/1
@dfn{synchronisation:} Suspends until Port is instantiated.

@dfn{behaviour:} Succeeds if Port is an input port.

@item is_oport(Port)
@findex is_oport/1
@dfn{synchronisation:} Suspends until Port is instantiated.

@dfn{behaviour:} Succeeds if Port is an output port.

@item unlock(Port)
@findex unlock/1
@dfn{synchronisation:} Suspends until Port is instantiated.

@dfn{behaviour:} Unlocks a pipe which has been locked by a
previous @code{look_pipe/2}.
The port must be owned by the current thread, otherwise the primitive fails.
This is used in the case where the term read is not the one expected.  The
pipe is unlocked so that another thread can re-read the same term.

@item close_port(Port)
@findex close_port/1
@dfn{synchronisation:} Suspends until Port is instantiated.

@dfn{behaviour:} Closes the specified port.
The port must be owned by the current
thread, otherwise the primitive fails.  @code{close_port/1} suspends if
the pipe is locked and fails if the port has a suspended operation
pending.  If an output port is closed, subsequent (and suspended) reads
from the input port will return @code{end_of_file}.  Closing an input
port does not affect the output port.  If both ports are closed, space
used for the pipe is reclaimed.

@item release_port(Port)
@findex release_port/1
@dfn{synchronisation:} Suspends until Port is instantiated.

@dfn{behaviour:} Releases ownership of the port to allow other
threads to use it.  The port
must be owned by the current thread, otherwise the primitive fails.
@code{release_port/1} suspends if the pipe is locked.
@end table

@node NetworkCommunication, Other, PipeCommunication, IC-PrologII
@section Network Communication Primitives

Parlog under IC-Prolog II has a large set of primitives for communication
over a network.  The set consists of an interface to TCP/IP library
calls and an alternative communication model based on the notion of
mailboxes.

The Parlog primitives are identical to those available under
the Prolog component of IC-Prolog II. Please refer to the Prolog
manual for further details.

@node Other,  , NetworkCommunication, IC-PrologII
@section Miscellaneous

@table @code
@item prolog
@findex prolog/0
@dfn{synchronisation:} No suspension.

@dfn{behaviour:} Switches the query evaluator from Parlog to Prolog
in the case where Prolog and Parlog share the same window.
Normally, Parlog and Prolog will each have their own windows.  
This is only used interactively as a top level goal.

@item parlog(G)
@findex parlog/1
@dfn{synchronisation:} Suspends until G is instantiated.

@dfn{behaviour:} Start executing the goal G as a separate Parlog process.
This is similar to meta-call @code{call/1} except that variables
are not instantiated and @code{parlog/1} returns immediately regardless
of the how long it takes to execute G or indeed whether it succeeds
or fails.  This primitive is most useful for setting up `background'
goals.

@item timeslice(N)
@findex timeslice/1
@dfn{synchronisation:} Suspends until N is instantiated.

@dfn{behaviour:} If N is the integer 0, time-slicing is switched off.
This has the effect of preventing runnable Prolog threads from
executing, thus allowing Parlog exclusive use of the processor.
If N is the integer 1, time-slicing is resumed.  This primitive
is used when atomicity is required or when critical code regions are
entered.

@item ensure_loaded(F)
@findex ensure_loaded/1
@dfn{synchronisation:} Suspends until F is instantiated.

@dfn{behaviour:} Loads the file F if not already loaded.  This primitive
can be safely used instead of @code{load/1} to ensure that the file is
loaded once and once only.
@end table

