This is Info file icp.info, produced by Makeinfo-1.55 from the input
file prolog.texi.

This file documents the IC Prolog ][ system version 0.96, dated
28 September 1993.

Copyright (C) 1992,1993 Imperial College, London.  All rights reserved.


File: icp.info,  Node: StringsAndAtoms,  Next: Threads,  Prev: ListHandling,  Up: Builtin Predicates

String and Atom Handling
========================

`name(?X,?L)'
     X is that atom or integer such that L is a list of the ASCII codes
     for its printed representation.
          | ?- name(hello, List), name(Hello, List).
          
          List = [104,101,108,108,111]
          Hello = hello
          
          | ?- A1='12', name(A1, List), name(A2, List).
          
          A1 = '12'
          List = [49,50]
          A2 = 12
          
          | ?- A1='12', name(A1, List), name(A2, List), A1=A2.
          
          no
          
          | ?- A1=12, name(A1, List), name(A2, List).
          
          A1 = A2 = 12
          List = [49,50]

`atom_chars(?X,?L)'
     X is the atom such that L is a list of the ASCII codes for its
     printed representation.
          | ?- A1='12', atom_chars(A1, List), atom_chars(A2, List).
          
          A1 = A2 = '12'
          List = [49,50]
          
          | ?- A1='12', atom_chars(A1, List), atom_chars(A2, List), A1=A2.
          
          A1 = A2 = '12'
          List = [49,50]
          
          | ?- A1=12, atom_chars(A1, List).
          
          no

`number_chars(?X,?L)'
     X is the number such that L is a list of the ASCII codes for its
     printed representation.

          | ?- A1='12', number_chars(A1, List).
          
          no
          
          | ?- A1=12, number_chars(A1, List), number_chars(A2, List).
          
          A1 = A2 = 12
          List = [49,50]

`numbervars(?TERM, +START, -END)'
     Transforms each of the variables in TERM into ground terms of the
     form `'$Var'(N)' where N is an integer greater than or equal to
     the integer START.
          | ?- numbervars(a(X,Y), 0, End), display(a(X,Y)).
          a($VAR(0),$VAR(1))
          X = A
          Y = B
          End = 2
     The first variable in TERM gets N equal to START while the
     second distinct variable gets START+1 and so on.  END is the value
     of N when the last variable has been grounded.

`concat(?X,?Y,?Z)'
     Z is instantiated to the atom formed by concatenating the printed
     representation of X with that of Y. The limit of the size of a
     single atom is 255 characters. If you try to construct a new atom
     with more than 255 characters the extra trailing characters will
     simply be ignored.
          | ?- concat(foo, bar, Full).
          
          Full = foobar
          
          | ?- concat(Start, bar, foobar).
          
          Start = foo
          
          | ?- concat(foo, End, foobar).
          
          End = bar

`concat_atom(?LIST,?ATOM)'
     This primitive concatenates a list of constants ?LIST into a single
     atom ?ATOM.  The constants may be numbers or atoms.

`pname(?T,?N)'
     This primitive converts between a Prolog term and an atom
     representing its print name.  If T is bound, N is bound to the
     atom of the print name of T.

     If N is bound, T is bound to the term whose print name is N.
          | ?- pname(a(X, 2), N).
          
          Unbound variable : X
          N = 'a(_0,2)'
          
          | ?- pname(T, 'a(X, 2)').
          
          T = a(_243,2)

`pname(?T,?N,?VNAMES,?VARS)'
     Same as `pname/2' but with better control of the print name of
     variables.  If VNAMES is given is a variable, N is bound to the
     atom of the print name of T, with each variable in list VARS being
     represented by the corresponding atom in list VNAMES.  In the
     second form, T is bound to the term whose print name is N, VARS is
     bound to a list of variables found in the term and VNAMES is bound
     to a list of the corresponding print names.
          | ?- pname(a(X, 2), N, ['V1'], [X]).
          
          Unbound variable : X
          N = 'a(V1,2)'
          
          | ?- pname(T, 'a(X, 2)', VNames, Vars).
          
          T = a(_273,2)
          VNames = ['X']
          Vars = [_273]
     This predicate is useful for meta-programming.

`copy_term(?TERM, ?COPYTERM)'
     Creates a copy of term TERM with new variables but preserving
     bindings
          | ?- copy_term(a(X, b(G,X)), Copy).
          
          Unbound variables : G, X
          Copy = a(_141,b(_146,_141))

`gensym(+PREFIX, -ATOM)'
     Creates an atom ATOM whose prefix is PREFIX and whose suffix is an
     integer. Successive calls to `gensym/2' are guaranteed to give
     different atoms.
          | ?- gensym(a,Atom1), gensym(a,Atom2), gensym(b, Atom3).
          
          Atom1 = a1
          Atom2 = a2
          Atom3 = b1


File: icp.info,  Node: Threads,  Next: Parlog,  Prev: StringsAndAtoms,  Up: Builtin Predicates

Threads
=======

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).

`fork(+GOAL)'
     Forks a child thread to run GOAL.  The current thread is not
     suspended.  The child thread must wait for a `resume' call or a
     time slice to start executing.

`fork(+GOAL,-TH)'
     Creates a child thread to run GOAL, a thread identifier TH is
     returned. The current thread is not suspended. The child thread
     must wait for a `resume' call or a time slice to start executing.

`qprolog(+GOAL)'
     Similar functionality to `fork/1', but without the overhead of
     creating a new thread.  The GOAL is executed in a background
     reserved thread.  Use this in preference to `fork/1' only when
     GOAL is simple, since complex queries will delay other calls to
     `qprolog/1'.

`new_thread(-TH)'
     This creates a new thread structure and binds TH to an integer
     identifier for the thread.  This low-level primitive is typically
     not used by the user directly.

`thread(?TH)'
     Returns the identifier of the current thread.

`kill_thread(+TH)'
     Kills the specified thread and reclaims the memory space.

`suspend'
     Sets the status of the current thread to unrunnable.  Note that
     this does not immediately suspend the thread, but merely removes
     it from the run queue.  The thread must be explicitly named in
     order to resume it.

`suspend(+TH)'
     Sets the status of the thread TH to unrunnable.  This removes the
     specified thread from the run queue.  The thread must be
     explicitly resumed using `resume/1' to continue executing.

`resume'
     Non-specific scheduler.  The next thread in the circular run queue
     resumes execution.

`resume(+TH)'
     Resume execution of the specified thread.  This is the only way to
     change the status of a thread from unrunnable to runnable.  If TH
     is 0, the next runnable thread is resumed.  `resume/1' returns an
     error if TH is not a currently valid thread.

`timeslice(+N)'
     If N is the integer 0, time-slicing is switched off.  This has the
     effect of preventing other runnable threads from executing, thus
     giving the current thread exclusive use of the processor.  If N is
     any other integer, time-slicing is resumed.  This primitive is
     used when atomicity is required or when critical code regions are
     entered.

`pipe(-OP, -IP)'
     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 `port(N)' where N is an
     integer.

`write_pipe(+OP, ?T)'
     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, `write_pipe/2' wakes it after T is written out to the pipe.

`look_pipe(+IP, -T)'
     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 `commit_read/1').
     `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,
     `look_pipe/2' binds T to the constant `end_of_file'.

`commit_read(+IP)'
     Removes the term previously read by `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.  `commit_read/1' fails if
     the pipe is not locked (i.e. no previous `look_pipe/2').

`read_pipe(+IP, ?T)'
     Reads a term T from the input port IP.  Semantically, this is
     equivalent to `look_pipe(IP,T)' followed sequentially by
     `commit_read(IP)'.

`empty_pipe(+IP)'
     Is true if pipe IP has no data to be read. %LOOK

`is_iport(+PORT)'
     Is true if PORT is an input port.

`is_oport(+PORT)'
     Is true if PORT is an output port.

`unlock(+PORT)'
     Unlocks a pipe which has been locked by a previous `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.

`close_port(+PORT)'
     Closes the specified port.  The port must be owned by the current
     thread, otherwise the primitive fails.  `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 `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.

`release_port(+PORT)'
     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.  `release_port/1' suspends if the pipe is locked.

`shell'
     This starts a read-eval-print loop in a new window to handle
     Prolog queries.  It is usually used as the goal to be executed in
     a new forked thread.

`exit'
     Kills the current thread and resumes another runnable thread, if
     any. This is usually used to exit a shell as started above a la
     Unix.


File: icp.info,  Node: Parlog,  Next: Miscellaneous,  Prev: Threads,  Up: Builtin Predicates

Prolog - Parlog Interface
=========================

`xparlog'
     Starts the parlog thread and redirects its console input and
     output to a new window under X11.  It also opens a pipe for
     communication between the prolog and parlog processes.  The new
     window may be used to type parlog queries directly or you may use
     `parlog/1' to call it from prolog.  Only one parlog thread may be
     started.

`parlog'
     Switches the query handler from prolog to parlog.  The first time
     that `parlog/0' is called, a parlog thread is started and a pipe
     is opened for communication between the prolog and parlog
     processes.  Subsequent calls just switch to the existing parlog
     thread.  This primitive is useful when X Windows is not available
     or if you wish to run ICP in an Emacs buffer.  To get back to
     prolog, type the parlog query `prolog/0'.

`parlog(+GOAL)'
     Passes a goal GOAL to the parlog thread to solve.

`close_parlog'
     Closes the communication port to parlog.


File: icp.info,  Node: Miscellaneous,  Prev: Parlog,  Up: Builtin Predicates

Miscellaneous Primitives
========================

`unix(+A)'
     Execute the atom A as a unix command.

`cd(+A)'
     Change current directory to A.

`cd'
     Change current directory to the user's home directory.

`ls'
     Execute the unix command `ls' to list the current directory.

`ls(DIR)'
     Execute the unix command `ls' to list the directory DIR.

`pwd'
     Display the path name of the current directory.

`edit(+FILE, +EDITOR)'
     Edit the file FILE using the editor, EDITOR.  If the filename does
     not have an extension, the suffix ``.pl'' will be added.

`edit(+FILE)'
     Edit the file FILE using the editor, stored as property `editor'
     (by default `vi').  If the filename does not have an extension,
     the suffix ``.pl'' will be added.

`vi(+FILE)'
     Edit the file FILE using the `vi' editor.

`out_of_date(+FILE, Type)'
     Is true if the file FILE(`.icp') is older than file FILE(.TYPE).
     The files are can exist anywhere on the current search path.

`max(+I,+J,-K)'
     K is bound to the greater of I and J.

`arb_member(?EL,?TERM)'
     Succeeds if EL is a subterm of TERM. This is a deterministic test.

`not_arb_member(?EL,?TERM)'
     Succeeds if EL is not a subterm of TERM.

`address(?V,-ADDRESS)'
     Binds ADDRESS to the heap-address of variable V.

`time(-TIME)'
     Binds TIME to CPU time (in 60ths of a second) since last call.

`realtime(-TIME)'
     Binds TIME to the time since 00:00:00 GMT, Jan. 1, 1970 measured in
     seconds (the Unix epoch).

`ctime(?TIME, ?YEAR, ?MONTH, ?DAY, ?HOUR, ?MINUTES, ?SECONDS)'
     If TIME is a number (as returned by realtime/1), binds the
     remaining arguments with the corresponding integer
     representations. Alternatively if the other arguments are
     integers, instantiates TIME.

`statistics(?KEYWORD, -LIST)'
     This gives various execution statistics. These statistics pertain
     to the thread in which the call is issued. For each of the values
     of KEYWORD, LIST is unified with a list of values.

    `runtime'
          `List = [TIME1,TIME2]' where the times are since the start of
          prolog execution and since the last call to `statistics/2'
          with `KEYWORD = runtime'. Both times are in milliseconds.

    `garbage_collection'
          `List = [NUMBER,BYTES,TIME]' where `Number' is the number of
          garbage collections, BYTES the total number of bytes
          collected and TIME the time, in milliseconds, spent doing the
          garbage collection.

`errno(?NUMBER, -MESSAGE)'
     If NUMBER is a variable, instantiates NUMBER to the `C' error
     number (`errno') of the underlying system. MESSAGE is the textual
     message for the error.

     If NUMBER is a number, MESSAGE is the textual message for the error
     corresponding to this number.

`getenv(+ENVNAME, -VALUE)'
     Gets the value VALUE of the Unix environment variable ENVNAME.

`debugicp'
     Drops into the WAM-level ICP debugger.

`noref'
     Displays on `user_error' a listing which gives the name and arity
     of the currently referenced but undefined static predicates.

`window_label(+NAME)'
     Sets the name in the xterm title bar to NAME.

`icon_label(+NAME)'
     Sets the name in the xterm icon to NAME.

`get_prolog_flag(+FLAG, -VALUE)'
     Gets the value,  VALUE, of the flag FLAG for the thread in which
     the goal appears. The currently supported flags are

    `debug'
          The values can be one of the atoms `on', `off'

    `undefined_predicate'
          The values can be one of `fail' `warning' `error'. The
          default is `error'.

`set_prolog_flag(+FLAG, -VALUE)'
     Sets the value,  VALUE, of the flag FLAG for the thread in which
     the goal appears. The currently supported flags are

`argc(-NUMBER)'
     The number of arguments passed to prolog at initialization. These
     must be prefixed by `-z'.

`argv(-LIST)'
     The list of arguments passed to prolog at initialization. These
     must be prefixed by `-z'.

`cursor(+STREAM, ?POS)'
     If POS is a variable, this returns the position in the stream
     STREAM.  If POS is an integer, the stream position is set to its
     value.

`shell_escape'
     Prompts the user for a goal to be executed.  This is a useful menu
     option to provide so that queries can be made from deep inside a
     user program.

`get_path(-PATHLIST)'
     This predicate returns a list of the directories which will be
     searched when prolog is trying to locate a file.

`set_path(+PATHLIST)'
     This predicate can be used to set the directories which will be
     searched when prolog is trying to locate a file.  PATHLIST is a
     list of directories, each of which is an atom.


File: icp.info,  Node: Tcp,  Next: Mailboxes,  Prev: Builtin Predicates,  Up: Top

TCP Interface
*************

* Menu:

* TcpIntro::                    Introduction to TCP/IP
* TcpConnected::                Connection Oriented Protocol
* TcpConnectionless::           Connectionless Oriented Protocol
* TcpMisc::                     Miscellaneous TCP Predicates
* TcpLow::                      Low Level TCP primitives
* TcpEg::                       Simple TCP Examples

To allow for the communication between different ICP processes, a TCP
interface is provided. To make the interface accessible to users who are
not experts at TCP and or socket level programming, we provide a
restricted subset of the full TCP functionality provided at the C level.
The intention was that simple communication can be written quickly
without knowledge of the underlying communication protocol.

The primitives described here are implemented for both the Prolog and
Parlog sub-systems in ICP.  The TCP interface is not part of the core
ICP system and must be loaded by a command of the form
     ?- ensure_loaded(tcp).
The Prolog and Parlog interfaces are distinct libraries and so must be
loaded separately.


File: icp.info,  Node: TcpIntro,  Next: TcpConnected,  Up: Tcp

Introduction to TCP/IP
======================

It is beyond the scope of this manual to give a full description of the
TCP/IP communication protocol. For details the reader is refered to
`Unix Network Programming' by W. Richard Stevens and to the Unix
documentation.

In TCP communications happen through "sockets" which are similar to
file handles used in file I/O. Inter-process communication occurs
between two "peers"; the source and destination addresses. An address
consists of two components

"network address"
     This specifies the IP address of the machine

"port"
     This allows multiple peers on a given machine

There are essentially two means of communication supported under the TCP
protocol, "connection" and "connectionless".


File: icp.info,  Node: TcpConnected,  Next: TcpConnectionless,  Prev: TcpIntro,  Up: Tcp

Connection Oriented Protocol
============================

A socket is created and "bound" to a particular "port" and "host
address". The host address indicates the machine with which to
communicate. Typically a single process on any one machine will listen
for data on a particular port. Once a socket has been bound, subsequent
reads on this socket do not require the specification of the source of
the data (tcp_send/2, tcp_send/3).  A connected server will typically
have the following form
        ...,
        tcp_server(Port, Socket),            % open and bind socket
        tcp_accept(Socket, NewSocket),       % accept connection
        tcp_recv(NewSocket, Term1),          % read from connection
        ...,
        tcp_send(NewSocket, Term2),          % write to connection
        ...,
        tcp_close(NewSocket),                % close connection
        ...,                                 % here could do more accepts
        tcp_close(Socket).                   % close socket
The corresponding clients which connect to the server would have the
following form
        ...,
        tcp_client(Port, Address, Socket),   % connect to server address and port
        tcp_send(Socket, Term1),             % send data to server
        ...,
        tcp_recv(Socket, Term2),             % receive data from server
        ...,
        tcp_close(Socket).

`tcp_server(+PORT, -SOCKET)'
`tcp_server(+PORT, -SOCKET, +ADDRESS)'
     This predicate may be used to initiate a connection-oriented
     server. It is defined as
          tcp_server(Port, Socket) :-
                  tcp_open(connection, Socket),
                  tcp_bind(Socket, Port),
                  tcp_listen(Socket).
     The three argument form passes the extra argument to `tcp_bind/3'.

`tcp_client(+PORT, +ADDRESS, -SOCKET)'
`tcp_client(+PORT, +ADDRESS, -SOCKET, +TIMEOUT)'
     This predicate may be used to initiate a connection-oriented
     client. It is defined as
          tcp_client(Port, Address, Socket, TimeOut) :-
                  tcp_open(connection, Socket),
                  tcp_connect(Socket, Port, Address, TimeOut).
     See `tcp_connect/4' for details about the arguments.

`tcp_accept(+SOCKET, -NEWSOCKET)'
`tcp_accept(+SOCKET, -NEWSOCKET, -PORT, -ADDRESS)'
`tcp_accept(+SOCKET, -NEWSOCKET, -PORT, -ADDRESS, +TIMEOUT)'
     In the case of the server in a connection oriented protocol after
     listening, the socket must accept connections from clients. This
     returns a new socket NEWSOCKET through which communication with
     the client specified by ADDRESS and PORT can proceed.  This is
     equivalent to the C fragment
          {
                  struct sockaddr_in add;
                  int socket=Socket, newsocket=NewSocket;
                  int length=sizeof(struct sockaddr_in);
          
                  newsocket = accept(socket,(struct sockaddr *) &add,
                          &length);
                  Address = ntohl(add.sin_addr.s_addr);
                  Port = ntohs(add.sin_port);
          }
     The variable TIMEOUT must have one of the values

    `block'
          The call will block until a connection is established

    `poll'
          This throws error 702 if immediate connection is not
          possible. By default this error simply fails but a user
          defined error handler can override this.

    `INTEGER'
          The call will block for INTEGER seconds after which if no
          connection is established error 702 is thrown.

`tcp_send(+SOCKET, +TERM)'
`tcp_send(+SOCKET, +TERM, +EFLAG)'
     This is used to send data on a connected socket. It can not be
     used for connectionless protocols as it does not specify the
     address of the recipient.  EFLAG must be one of the following atoms

    `normal'
          Normal data in encoded form

    `raw'
          Normal data. Suitable for communication with non prolog
          processes. Raw data must be a prolog atom.

`tcp_recv(+SOCKET, -TERM)'
`tcp_recv(+SOCKET, -TERM, +EFLAG)'
`tcp_recv(+SOCKET, -TERM, +EFLAG, +TIMEOUT)'
     Is used to receive data from a socket. The variable +TIMEOUT must
     have one of the values

    `block'
          The call will block until a connection is established

    `poll'
          This throws error 702 if immediate connection is not
          possible. By default this error simply fails but a user
          defined error handler can override this.

    `INTEGER'
          The call will block for INTEGER seconds after which if no
          connection is established error 702 is thrown.

     `tcp_recv/2' is equivalent to the following definition
          tcp_recv(Socket, Term) :-
                  tcp_recv(Socket, Term, normal, block).
     EFLAG must be one of the following atoms

    `normal'
          Normal data in encoded form

    `raw'
          Normal data. Suitable for communication with non prolog
          processes. Raw data must be a prolog atom.

    `peek'
          Used to determine if there is normal data without removing it
          from the buffer.

    `peek_raw'
          Used to determine if there is raw data without removing it
          from the buffer.


File: icp.info,  Node: TcpConnectionless,  Next: TcpMisc,  Prev: TcpConnected,  Up: Tcp

Connectionless Oriented Protocol
================================

Here the socket is not associated with any particular port or host
address. Hence to send data, the destination port and host address must
be specified (tcp_sendto/4, tcp_sendto/5)

An example of a connectionless server follows
        tcp_connectionless(ServerPort, Socket),        % open socket
        tcp_recvfrom(Socket, Term1, Port, Machine),    % receive data from client
        ...,
        tcp_sendto(Socket, Term2, Port, Machine),      % send data to client
        ...,
        tcp_close(Socket).

        tcp_connectionless(ClientPort, Socket),
        tcp_sendto(Socket, Term1, Port, Machine),      % send data to server
        ...,
        tcp_recvfrom(Socket, Term2, Port, Machine),    % receive data from server
        ...,
        tcp_close(Socket).

`tcp_connectionless(+PORT, -SOCKET)'
     This predicate may be used to initiate a connectionless server or
     client. It is defined as
          tcp_connectionless(Port, Socket) :-
                  tcp_open(connectionless, Socket),
                  tcp_bind(Socket, Port).

`tcp_broadcast(+PORT, -SOCKET)'
     This predicate may be used to initiate a broadcast socket. It is
     defined as
          tcp_broadcast(Port, Socket) :-
                  tcp_open(broadcast, Socket),
                  tcp_bind(Socket, Port).
     Typically, PORT is specified as 0, which lets the system choose an
     unused port number.

`tcp_sendto(+SOCKET, +TERM, +PORT, +ADDRESS)'
`tcp_sendto(+SOCKET, +TERM, +PORT, +ADDRESS, +EFLAG)'
     This is used to send data on either a connected or connectionless
     socket.

     EFLAG must be one of the following atoms

    `normal'
          Normal data in encoded form

    `raw'
          Normal data. Suitable for communication with non prolog
          processes. Raw data must be a prolog atom.

`tcp_sendbr(+SOCKET, +TERM, +PORT)'
`tcp_sendbr(+SOCKET, +TERM, +PORT, +EFLAG)'
     This broadcasts on the specified port. The socket must have been
     opened in broadcast mode.

     EFLAG must be one of the following atoms

    `normal'
          Normal data in encoded form

    `raw'
          Normal data. Suitable for communication with non prolog
          processes. Raw data must be a prolog atom.

`tcp_recvfrom(+SOCKET, -TERM, -PORT, -ADDRESS)'
`tcp_recvfrom(+SOCKET, -TERM, -PORT, -ADDRESS, +EFLAG)'
`tcp_recvfrom(+SOCKET, -TERM, -PORT, -ADDRESS, +EFLAG, +TIMEOUT)'
     Is used to receive data from a socket, also returning the IP
     address and port of the sender. The variable +TIMEOUT must have
     one of the values

    `block'
          The call will block until a connection is established

    `poll'
          This throws error 702 if immediate connection is not
          possible. By default this error simply fails but a user
          defined error handler can override this.

    `INTEGER'
          The call will block for INTEGER seconds after which if no
          connection is established error 702 is thrown.

     `tcp_recvfrom/4' is equivalent to the following definition
          tcp_recvfrom(Socket, Term, Port, Address) :-
                  tcp_recvfrom(Socket, Term, Port, Address, normal, block).
     EFLAG must be one of the following atoms

    `normal'
          Normal data in encoded form

    `raw'
          Normal data. Suitable for communication with non prolog
          processes. Raw data must be a prolog atom.

    `peek'
          Used to determine if there is data without removing it from
          the buffer.


File: icp.info,  Node: TcpMisc,  Next: TcpLow,  Prev: TcpConnectionless,  Up: Tcp

Miscellaneous TCP Predicates
============================

This section describes some useful TCP primitives which are not
restricted to either connection or connectionless protocols.  The are
typically used to enquire about the state of the communication channel.

`tcp_close(+SOCKET)'
     This predicate is used to close a socket obtained with one of the
     calls `tcp_socket/3', `tcp_open/2' or `tcp_accept/5'.

`tcp_checkconn(+SOCKET)'
     This predicate succeeds if the socket is ready to be written to and
     fails if it is not.

`tcp_checkrecv(+SOCKET)'
`tcp_checkrecv(+SOCKET, +EFLAG)'
     This predicate succeeds if the socket is ready to be read from and
     fails if it is not.

`tcp_getsockaddr(+SOCKET, -PORT, -ADDRESS)'
     This predicate returns the IP address ADDRESS and port number of
     this side of a socket.
          | ?- tcp_server(5569, Socket).
          
          Socket = 0
          
          | ?- tcp_getsockaddr(0, Port, Address).
          
          Port = 5569
          Address = 2460554497
          
          | ?- tcp_gethost(Name, Address).
          
          Name = laotzu
          Address = 2460554497

`tcp_getpeeraddr(+SOCKET, -PORT, -ADDRESS)'
     This predicate returns the IP address ADDRESS and port number of
     the far side of a connected socket.
          | ?- tcp_server(5569, Socket).
          
          Socket = 0
          
          | ?- tcp_accept(1, NewSocket, NewPort, Address).
          
          NewSocket = 1
          NewPort = 1108
          Address = 2460554499
          
          | ?- tcp_getpeeraddr(1, Port, Address).
          
          Port = 1108
          Address = 2460554499

`tcp_currenthost(-NAME, -ADDRESS)'
     Gets the name and address of the current host.
          | ?- tcp_currenthost(Name, Address).
          
          Name = sophia
          Address = 2460554499

`tcp_gethost(?NAME, ?ADDRESS)'
     The machine of name NAME has IP address ADDRESS.  The predicate is
     deterministic.
          | ?- tcp_gethost(laotzu, Address).
          
          Address = 2460554497
          
          | ?- tcp_gethost(Name, 2460554497).
          
          Name = laotzu
          
          | ?- tcp_gethost('146.169.21.1', L).
          
          L = 2460554497

`tcp_getport(?NAME, ?PROTOCOL, ?PORT)'
     The named port NAME, is on port PORT, using protocol PROTOCOL.
     These values correspond to the entries in file `/etc/services'.
     Valid modes of use are `tcp_getport(+NAME,?PROTOCOL, ?PORT)' and
     `tcp_getport(?NAME, ?PROTOCOL, +PORT)'.
          | ?- tcp_getport(login, Protocol, Port).
          
          Protocol = tcp
          Port = 513
          
          | ?- tcp_getport(Name, Protocol, 513).
          
          Name = who
          Protocol = udp
          
          | ?- tcp_getport(Name, tcp, 513).
          
          Name = login
     The predicate is deterministic; It only finds one port per
     name.

`tcp_real_socket(+SOCKET, -HANDLE)'
     Predicates which return socket identifiers (such as `tcp_open/2'
     return integers >= 0 which are unique identifiers for the socket.
     Given a socked identifier SOCKET, `tcp_real_socket/2' returns the
     file handle for the socket. This is useful if user defined
     predicates require this descriptor.


File: icp.info,  Node: TcpLow,  Next: TcpEg,  Prev: TcpMisc,  Up: Tcp

Low Level TCP primitives
========================

This section describes other less frequently used TCP primitives.  They
are provided here for completeness.

`tcp_open(+TYPE, -SOCKET)'
     The predicate `tcp_open/2' is defined in terms of `tcp_socket/3'
     providing a higher level method of openning sockets.  Opens a TCP
     connection of type TYPE returning the identifier SOCKET.  TYPE is
     one of the following atoms

    `connection'
          A connected socket is opened. This provides sequenced,
          reliable two-way connection based byte streams. A stream
          socket must be in a connected state before any data may be
          sent or received on it. A connection to another socket is
          created with a `tcp_connect/4' call.  Once connected, data
          may be transferred using `tcp_send/3' and `tcp_recv/4' calls.
          When a session has been completed a `close/1' call may be
          performed.  This is equivalent to the C call
               sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
          and is defined as
               tcp_open(connection, Socket) :-
                       tcp_socket(sock_stream, ipproto_ip, Socket).

    `connectionless'
          A connectionless socket is opened. This provides unreliable
          messages of a fixed (typically small) maximum length. Data
          may be transferred using `tcp_sendto/5' and `tcp_recvfrom/5'
          calls.  This is equivalent to the C call
               sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
          and is defined as
               tcp_open(connectionless, Socket) :-
                       tcp_socket(sock_dgram, ipproto_ip, Socket).

    `broadcast'
          A broadcast socket is opened. This is a connectionless socket
          intended for broadcasting messages to the local network.
          Messages written to such a socket may be received by any
          machines listening on the local network.  These are
          connectionless, unreliable messages of a fixed (typically
          small) maximum length. The messages will be delivered to all
          broadcast endpoints in the network.  Data may be transferred
          using `tcp_send/3' and `tcp_recvfrom/5' calls.  This is
          equivalent to the C fragment
               {
                       int i = 1;
                       sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
                       setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&i,
                               sizeof(int));
               }
          and is defined as
               tcp_open(broadcast, Socket) :-
                       tcp_socket(sock_dgram, ipproto_ip, Socket),
                       tcp_setsockopt(Socket, so_broadcast, 1).

`tcp_bind(+SOCKET, +PORT)'
`tcp_bind(+SOCKET, +PORT, +ADDRESS)'
     Once a socket has been opened by a call to `tcp_open/2' or
     `tcp_socket/3', and with the exception of a connected client, it
     should be bound to a port and an IP address. Some ports -
     typically 1-1023 are reserved by the system. If PORT=0 the system
     will assign an available port. The predicate `tcp_getport/3' may
     be used to obtain the port number of a port named in
     `/etc/services'.  This is an interface to `tcp_bind/3' and is
     defined as
          tcp_bind(Socket, Port) :- tcp_bind(Socket, Port, inaddr_any).
     `tcp_bind/3' is as `tcp_bind/2' except that the variable ADDRESS
     is either the atom `inaddr_any' or an IP address (integer such as
     2460554498, or the equivalent atom in dot notation '146.169.21.2')
     of an ethernet interface of the machine (obtained from the
     predicate `tcp_gethost/2').  This is only important for machines
     which have more than one ethernet interface.  Specifying an IP
     address means that only messages on that network will be
     sent/received.  If ADDRESS is `inaddr_any' then all the interfaces
     are used by default.  This is equivalent to the following C
     fragment.
          {
                  struct sockaddr_in server;
                  u_long machine = Address
                  u_short port = Port
                  int socket = Socket;
          
                  server.sin_family = AF_INET;
                  server.sin_addr.s_addr = htonl(machine);
                  server.sin_port = htons(port);
                  bind(socket, (struct sockaddr *) &server, sizeof(server));
          }

`tcp_connect(+SOCKET, +PORT, +ADDRESS)'
`tcp_connect(+SOCKET, +PORT, +ADDRESS, +TIMEOUT)'
     In the case of the client in a connection oriented protocol the
     socket needs to be connected to the server.  The ADDRESS may be
     specified as a machine name (e.g. confucius, or
     'confucius.doc.ic.ac.uk'), or the IP address in integer form (e.g.
     2460554498) or an atom in dot notation form (e.g. '146.169.21.2').

     `tcp_connect/4' is equivalent to the C fragment
          {
                  struct sockaddr_in add;
                  u_long machine=Address;
                  u_short port=Port;
                  int socket=Socket;
          
                  add.sin_family = AF_INET;
                  add.sin_addr.s_addr = htonl(machine);
                  add.sin_port = htons(port);
                  fcntl(socket, F_SETFL, FASYNC);
                  connect(socket, (struct sockaddr *) &add, sizeof(add));
                  fcntl(socket, F_SETFL, 0);
          }
     The variable TIMEOUT must have one of the values

    `block'
          The call will block until a connection is established

    `poll'
          This throws error 702 if immediate connection is not
          possible. By default this error simply fails but a user
          defined error handler can override this.

    `INTEGER'
          The call will block for INTEGER seconds after which if no
          connection is established error 702 is thrown.

`tcp_listen(+SOCKET)'
     In the case of the server in a connection oriented protocol after
     opening, and binding a socket it must specify a backlog for
     incoming connections from clients. The backlog size is 5.  It
     corresponds to the C fragment:
          {
                  int socket=Socket;
          
                  listen(socket, 5);
          }

`tcp_socket(+TYPE, +PROTOCOL, -SOCKET)'
     This predicate is used to open a TCP socket. The variable TYPE
     must be one of

    `sock_stream'
          For use in connected (stream) communication

    `sock_dgram'
          For use in connectionless (datagram) communication

    `sock_raw'
          For use in raw communication

     The variable PROTOCOL must be one of

    `ipproto_ip'
          Suitable for any TYPE

    `ipproto_udp'
          Suitable for TYPE=`sock_dgram'

    `ipproto_tcp'
          Suitable for TYPE=`sock_stream'

    `ipproto_icmp'
          Suitable for TYPE=`sock_raw'

    `ipproto_raw'
          Suitable for TYPE=`sock_raw'

     The variable SOCKET is bound to an integer which can be used in
     subsequent TCP operations.

`tcp_setsockopt(+SOCKET, +OPTNAME, +VALUE)'
     This predicate allows the setting of various options on sockets.
     The supported values of OPTNAME are the following

    `so_debug'
          turn on debugging info recording

    `so_reuseaddr'
          allow local address reuse

    `so_keepalive'
          keep connections alive

    `so_dontroute'
          just use interface addresses

    `so_broadcast'
          permit sending of broadcast msgs

    `so_oobinline'
          leave received OOB data in line

    `so_sndbuf'
          send buffer size

    `so_rcvbuf'
          receive buffer size

    `so_sndtimeo'
          send timeout

    `so_rcvtimeo'
          receive timeout

     The call is an interface to the UNIX system call `setsockopt(2)'
     and is equivalent to the following C fragment
          {
                  int val = Val, opt = Opt, sock = Sock;
                  setsockopt(sock,SOL_SOCKET,opt,(char *)&val,sizeof(val));
          }

`tcp_getsockopt(+SOCKET, +OPTNAME, +VALUE)'
     This predicate allows the getting of various options on sockets.
     The supported values of OPTNAME are the following

    `so_debug'
          turn on debugging info recording

    `so_reuseaddr'
          allow local address reuse

    `so_keepalive'
          keep connections alive

    `so_broadcast'
          permit sending of broadcast msgs

    `so_oobinline'
          leave received OOB data in line

    `so_sndbuf'
          send buffer size

    `so_rcvbuf'
          receive buffer size

    `so_sndtimeo'
          send timeout

    `so_rcvtimeo'
          receive timeout

    `so_error'
          get error status and clear

    `so_type'
          get socket type

     The call is an interface to the UNIX system call `getsockopt(2)'
     and is equivalent to the following C fragment
          {
                  int val = Val, opt = Opt, sock = Sock;
                  getsockopt(sock,SOL_SOCKET,opt,(char *)&val,sizeof(val));
          }


File: icp.info,  Node: TcpEg,  Prev: TcpLow,  Up: Tcp

Simple TCP Examples
===================

* Menu:

* TcpEgConnected::              Connected Sockets
* TcpEgConnectionless::         Connectionless Sockets
* TcpEgBroadcast::              Broadcast Sockets


File: icp.info,  Node: TcpEgConnected,  Next: TcpEgConnectionless,  Up: TcpEg

Connected Sockets
-----------------

The program below is an example of using the TCP connection protocol.
The full source code can be found in the file
`$ICP_INSTALLDIR/examples/tcp/simple_connected.pl'.  A more
sophisticated example is in file
`$ICP_INSTALLDIR/examples/tcp/connected.pl'.

To run the example, two ICP processes should be started and the command
     | ?- server.
run on one process while
     | ?- client(Port, Address).
is run on the other.  Input on the client is echoed by the server.

     /********************** connected server *************************/
     server :-
         tcp_server(0, Socket),
         tcp_getsockaddr(Socket, Port, Address),
         write('use '), write(client(Port, Address)), write('.\n'),
         server_loop(ok, Socket).
     
     server_loop(stop, Socket) :- !, tcp_close(Socket).
     server_loop(_, Socket) :-
         tcp_accept(Socket, NewSocket),
         process_request(ok, NewSocket, T),
         server_loop(T, Socket).
     
     process_request(stop, Socket, stop) :- !, tcp_close(Socket).
     process_request(end, Socket, end) :- !, tcp_close(Socket).
     process_request(_, Socket, Final) :-
         tcp_recv(Socket, T),
         writenl(tcp_recv(Socket, T)),
         process_request(T, Socket, Final).
     process_request(_, Socket, end) :- !, tcp_close(Socket).
     
     /*********************** connected client *************************/
     client(Port, Address) :-
         tcp_client(Port, Address, Socket),
         client_loop(ok, Socket).
     
     client_loop(stop, Socket) :- !, tcp_close(Socket).
     client_loop(end, Socket) :- !, tcp_close(Socket).
     client_loop(_, Socket) :-
         write('enter term, "end" ends this channel, "stop" stops server> '),
         flush,
         read(T),
         tcp_send(Socket, T),
         client_loop(T, Socket).


File: icp.info,  Node: TcpEgConnectionless,  Next: TcpEgBroadcast,  Prev: TcpEgConnected,  Up: TcpEg

Connectionless Sockets
----------------------

This example can be found in the file
`$ICP_INSTALLDIR/examples/tcp/connectionless.pl'.

     /************************ connectionless server *****************************/
     server :-
         tcp_connectionless(0, Socket),
         tcp_getsockaddr(Socket, Port, Address),
         writeseqnl(['server Port:', Port, '  Address:', Address]),
         writeseqnl(['Server started.',
             'You can start a client with the following command: ','\n\t',
             client(Port, Address),'.']),
         server_loop(ok, Socket).
     
     server_loop(stop, Socket) :- !, tcp_close(Socket).
     server_loop(_, Socket) :-
         tcp_recvfrom(Socket, Data, Port, Address),
         writeseqnl(['got>', Data, '<', 'from Port:', Port,
                                        '  Address:', Address]),
         server_loop(Data, Socket).
     
     /************************ connectionless client *****************************/
     client(Port, Address) :-
         tcp_connectionless(0, Socket),
         client_loop(ok, Socket, Port, Address).
     
     client_loop(stop, Socket, _, _) :- !, tcp_close(Socket).
     client_loop(end, Socket, _, _) :- !, tcp_close(Socket).
     client_loop(_, Socket, Port, Address) :-
         write('enter term, "end" ends this channel, "stop" stops server> '),
         flush,
         read(Data),
         tcp_sendto(Socket, Data, Port, Address),
         client_loop(Data, Socket, Port, Address).


File: icp.info,  Node: TcpEgBroadcast,  Prev: TcpEgConnectionless,  Up: TcpEg

Broadcast Sockets
-----------------

This example can be found in the file
`$ICP_INSTALLDIR/examples/tcp/broadcast.pl'.


File: icp.info,  Node: Mailboxes,  Next: Foreign Interface,  Prev: Tcp,  Up: Top

Mailbox-based communication model
*********************************

* Menu:

* MbxIntroduction::             Introduction to Mailboxes
* MailboxServer::               Mailbox Server
* RestrictedAccess::            Restricting Access
* StartingMailboxes::           Starting Mailboxes
* MailboxPrimitives::           Mailbox Primitives

TCP works well for applications which naturally map onto the
client-server model.  There is an asymmetry between the clients and the
server.  However, in the simple case of two processes having a
conversation, it seems to be an unnecessary overhead and confusing
complication to force one process to be the server and somehow provide
a service to the client, when it is much more natural to think of them
as two symmetrical processes.

In TCP, the instrument of communication is a socket.  A socket is one
end of a communication channel.  To set up a channel between a server
and a client, two sockets are created (one by the server and the other
by the client) and are then connected to each other.  This is analogous
to a telephone conversation where two telephones are required to set up
a connection.  As with telephones, TCP communication is strictly
one-to-one.  There are no facilities to set up one-to-many or
many-to-one conversations.

In TCP, every communication channel set up between a server and a
client is a separate network connection.  The system overheads of
creating sockets and setting up connections over the network become
significant if the conversations are short and there are many such
conversations.  For example, if ten processes on one machine are
talking to ten processes on another machine, there will be ten network
connections between the two machines.

These disadvantages can be overcome by providing a higher level
abstraction that is more powerful and simpler to use.  Mailboxes
provide such an abstraction.

This section documents the Mailbox primitives.  These primitives are
available to both the Prolog and Parlog sub-systems of ICP.  The
Mailbox interface is not part of the core ICP system and must be loaded
by a command of the form
     ?- ensure_loaded(mailbox).
The Prolog and Parlog interfaces are distinct libraries and so must be
loaded separately.

Note that only the `blocking' form of the mailbox primitives are
currently implemented.


File: icp.info,  Node: MbxIntroduction,  Next: MailboxServer,  Up: Mailboxes

Introduction to Mailboxes
=========================

In the mailbox model, the instrument of communication is a mailbox.  A
mailbox is simply a repository for messages.  Mailboxes may be created
freely by any process.  Messages can be sent to and removed from a
mailbox.  Instead of having to create two sockets to communicate, we
now need to create only one mailbox.  For two processes to communicate,
the sender places a message in the mailbox, and the receiver removes it
from the same mailbox.  A mailbox can store multiple messages.  Messages
are kept in arrival order so that it naturally simulates stream
communication.

* Menu:

* MessagePeeking::              Message Peeking
* TwowayCommunication::         Two-way Communication
* MultiwayCommunication::       Multi-way Communication


File: icp.info,  Node: MessagePeeking,  Next: TwowayCommunication,  Up: MbxIntroduction

Message Peeking
---------------

When a message is read from a mailbox, there is an option to not remove
it.  The message can remain in the mailbox.  This is so that a
receiving process can determine whether it should be left for another
process to handle.  This can occur because multiple processes may be
reading from the same mailbox.  When a message is being checked in this
way, further reads from this mailbox must wait until a decision has
been made regarding the message.  The options are to commit the read
and remove the message, or to discard the read and leave it in the
mailbox.


File: icp.info,  Node: TwowayCommunication,  Next: MultiwayCommunication,  Prev: MessagePeeking,  Up: MbxIntroduction

Two-way Communication
---------------------

Messages in a mailbox may be read by any process, including the process
that sent it.  This makes it difficult (though not impossible) to
implement two-way communication using only one mailbox.  Mailboxes are
best used when only one receiver reads messages from it.  Since there
is very little cost associated with creating new mailboxes, two-way
communication should be carried out using two mailboxes.

