Host server I/O functions
Send_msg()/Rec_msg() message passing primitives
Libraries available for the PROLOG Process Layer:
PROLIB : Auxiliary PROLOG Predicates
STRLIB String processing routines
MSGLIB : Message Passing Primitives
IOLIB : Host Server I/O
WINLIB : Window Management Predicates
GRAPHLIB Graphics functions
SYSTEM : Transputer Specific Predicates
HOSTLIB Host server functions
The PROLOG Process Layer presents something like 'native' sequential communicating processes ( CSP ). This is the lowest layer to be used by a PROLOG programmer: After the boot-up of a transputer network, one PROLOG process is created on each node. No resource management is installed at this point and the user is free to tell the process to perform any task independent of all other processes in the network.
Writing Applications for the PROLOG Process Layer , Low Level 'C' Layer , Client-Server Layer , Object Layer
After a Transputer network is booted, each node loads by default the file 'SYSMAN.LKD' into its memory and starts to execute the 'goal()' predicate of this file. The user is now responsible to establish some kind of communication mechanism to access and manage the resources in the network.
Two predicates give a programmer the capability to implement a customized communication scheme:
gets the highest Tid in the network. All Transputer Ids from 1 to MaxTid are available.
create a new process on Transputer 'Tid' with name Name and MemSize kB of memory. The return value 'Pid' is the process id of the new process
With your BAP release, a default 'SYSMAN.LKD' file is provided that establishes the Client-Server Layer that is described in this manual. It is advisable for every application programmer to use this default resource management because it covers all low level system management while it allows the user to establish his own communication schemes on top of the Client-Server Layer. You just need to allocate a server and to send him an exec(Call) , with Call being a predicate that otherwise you would have named goal() (see above) ). Because of this, those two predicates are not described in the library reference of this version.
A BAP Process is an ordinary, sequentially running PROLOG program. The flow of control is exactly identical to the standard defined by Clocksin & Mellish. Each PROLOG process contains its own local database, too. This means that, if just one Transputer is available, BAP may be used instead of an ordinary sequential PROLOG, without any parallel extensions. This is essential to build up a CSP model ( Communicating Sequential Processes ) because each process must behave like a standard PROLOG process. In this paradigm parallelism is introduced by the means of library routines.
Each process owns a (PROLOG-) Database and a mail box .
create_processes() , process_name()
Is a 'packed' PROLOG term. 'Packed' means that a PROLOG term of any size is stored into memory so that it can be transmitted by the low level router. A receiving PROLOG process 'unpacks' a message, so that it can be treated by the prolog unification and inference mechanisms.
rec_msg() , send_msg()
Each PROLOG process owns exactly one mail box. Messages that are sent to this process appear in its mail box (first in - first out). The 'rec_msg()' predicate returns the topmost message of the mail box
rec_msg() , send_msg()
Each PROLOG process owns exactly one database. The database is accessed by the PROLOG built-in predicates assert() and retract() .
The PROLOG process layer introduces the basic communicating constructs of BAP: Send_msg() and rec_msg() . These routines can be compared with the primitive Transputer chan_in/chan_out channel communication routines in OCCAM or C. The difference is that send_msg()/rec_msg() do not need Transputer channels and that they transfer 'messages' instead of bytes.
The following example shows the usage of these new routines:
Sender Process Receiver Process
get_receiver_id(ReceiverId), send_msg(ReceiverId,fac(5,_)), rec_msg(Sender,Msg), call(Msg), send_msg(Sender,Msg), rec_msg(ReceiverId,ReplyMessage), ReplyMessage = fac(5,X), write('Factorial(5,",X,")\n").
The Sender process calls a routine to get the an id of a Receiver process 'get_receiver_id()' (This may be any kind of routine that is able to determine a valid process id of a suitable process). 'Send_msg()' directly sends the term 'fac(5,_)' to the Receiver process. Rec_msg() is called and suspends the Sender process until the reply message arrives.
The Receiver process receives the message using 'rec_msg()', executes it by call() and returns the result to the Sender.
The Sender process receives the reply message (ReplyMessage = fac(5,120)'). Now 'fac(5,_)' and 'fac(5,120)' are unified so that 'X' is bound to '120' and the result is displayed.
Send_msg() uses the address of a certain process instead of a communication channel. This process address consists of a Transputer ID and a Process Id (Tid/Pid). The data to be send, a PROLOG message , is just an ordinary PROLOG term. Such a term (that may be a for example a single integer or the entire parse tree of a compiler) becomes 'packed' into a binary representation. This representation is split into blocks that are transmitted to the destination process. Here the messages becomes reassembled to a PROLOG term.
Such a message arrives in the mail box of the destination process. This mail box is an independently running 'C' process that is always ready to receive messages from the message passing system. These messages are stacked for later access by the rec_msg() predicate.
The execution of a rec_msg() suspends a process in the case, that no message is available (the mail box is empty). If a message is present, rec_msg(SenderId,Message) succeeds and continues with its arguments bound to the id of the sender (SenderId) and the message term (Message) respectively.
The picture above shows a 'Client' process that sends a message into the mail box of a process called 'Server'. The message is stored at the end of the mail box asynchronously to the actions of the server process. The Server removes the topmost message from the mail box to execute.
If 'send_msg(DestId,Msg)' is called, the term that actually leaves the process is: 'msg(msg(Tid,Pid), Msg)'. The reason for these two 'msg' structures 'around' the message is to tell the receiving process who did send the message. When 'rec_msg()' pulls the message out of its 'mail box', it splits the message into the 'Sender Id' ('msg(Tid,Pid)') and the message body 'Msg'. The 'Sender Id' may be ignored or may be used later to pass a reply to the sender of the message. These conventions only appear at debug time and are subject to changes.
The system management 'sysman' is - obviously - an example of Process Level programming. The source code ('sysman.bap') is included in the release version of BAP.