Go to the first, previous, next, last section, table of contents.

Linda--Process Communication

Linda is a concept for process communication.

For an introduction and a deeper description, see [Carreiro & Gelernter 89a] or [Carreiro & Gelernter 89b], respectively.

One process is running as a server and one or more processes are running as clients. The processes are communicating with sockets and supports networks.

The server is in principle a blackboard on which the clients can write (out/1), read (rd/1) and remove (in/1) data. If the data is not present on the blackboard, the predicates suspend the process until they are available.

There are some more predicates besides the basic out/1, rd/1 and in/1. The in_noblock/1 and rd_noblock/1 does not suspend if the data is not available--they fail instead. A blocking fetch of a conjunction of data can be done with in/2 or rd/2.

Example: A simple producer-consumer. In client 1:

producer :-
       produce(X),
       out(p(X)),
       producer.

produce(X) :- .....

In client 2:

consumer :- 
       in(p(A)),
       consume(A),
       consumer.

consume(A) :- .....

Example: Synchronization

       ...,
       in(ready),  %Waits here until someone does out(ready)
       ...,

Example: A critical region

       ...,
       in(region_free),  % wait for region to be free
       critical_part,
       out(region_free), % let next one in
       ...,

Example: Reading global data

       ...,
       rd(data(Data)),
       ...,

or, without blocking:
       ...,
       rd_noblock(data(Data)) ->
             do_something(Data)
       ;     write('Data not available!'),nl
       ),
       ...,

Example: Waiting for one of several events

       ...,
       in([e(1),e(2),...,e(n)], E),
%  Here is E instantiated to the first tuple that became available
       ...,

Server

The server is the process running the "blackboard process". It is an ordinary SICStus process which can be run on a separate machine if necessary.

To load the package, enter the query

| ?- use_module(library('linda/server')).

and start the server with linda/0 or linda/1.

linda
Starts a Linda-server in this SICStus. The network address is written to current output stream as Host:PortNumber.
linda(+Hook)
Starts a Linda-server in this SICStus. When it is started, a goal passed in Hook is evaluated. Hook must have the form Address-Goal where Address must be unifiable with Host:Port and Goal must be instantiated to a goal. Example:
| ?- linda((Host:Port)-(my_module:mypred(Host,Port))).
will call mypred/2 in module my_module when the server is started. mypred/2 could start the client-processes, save the address for the clients etc. Note that the module must be present in Goal.

Client

The clients are one or more sicstus processes which have connection(s) to the server.

To load the package, enter the query

| ?- use_module(library('linda/client')).

Some of the following predicates fail if they don't receive an answer from the Linda-server in a reasonable amount of time. That time is set with the predicate linda_timeout/2.

linda_client(+Address)
Establishes a connection to a Linda-server specified by Address. The Address is of the format Host:PortNumber as given by linda/0 and linda/1. It is not possible to be connected to two Linda-servers in the same time. This predicate can fail due to a timeout.
close_client
Closes the connection to the Linda-server.
linda_timeout(?OldTime, ?NewTime)
This predicate controls Linda's timeout. OldTime is unified with the old timeout and then timeout is set to NewTime. The value is either off or of the form Seconds:Milliseconds. The former value indicates that the timeout mechanism is disabled, that is, eternal waiting. The latter form is the timeout-time.
out(+Tuple)
Places the tuple Tuple in Linda's tuple-space.
in(?Tuple)
Removes the tuple Tuple from Linda's tuple-space if it is there. If not, the predicate blocks until it is available (that is, someone performs an out/1).
in_noblock(?Tuple)
Removes the tuple Tuple from Linda's tuple-space if it is there. If not, the predicate fails. This predicate can fail due to a timeout.
in(+TupleList, ?Tuple)
As in/1 but succeeds when either of the tuples in TupleList is available. Tuple is unified with the fetched tuple. If that unification fails, the tuple is not reinserted in the tuple-space.
rd(?Tuple)
Succeeds if Tuple is available in the tuple-space, suspends otherwise until it is available. Compare this with in/1: the tuple is not removed.
rd_noblock(?Tuple)
Succeeds if Tuple is available in the tuple-space, fails otherwise. This predicate can fail due to a timeout.
rd(+TupleList, ?Tuple)
As in/2 but does not remove any tuples.
bagof_rd_noblock(?Template, +Tuple, ?Bag)
Bag is the list of all instances of Template such that Tuple exists in the tuple-space. The behavior of variables in Tuple and Template is as in bagof/3. The variables could be existentially quantified with ^/2 as in bagof/3. The operation is performed as an atomic operation. This predicate can fail due to a timeout. Example: Assume that only one client is connected to the server and that the tuple-space initially is empty.
| ?- out(x(a,3)), out(x(a,4)), out(x(b,3)), out(x(c,3)).

yes
| ?- bagof_rd_noblock(C-N, x(C,N), L).

C = _32,
L = [a-3,a-4,b-3,c-3],
N = _52 ?

yes
| ?- bagof_rd_noblock(C, N^x(C,N), L).

C = _32,
L = [a,a,b,c],
N = _48 ?

yes

Go to the first, previous, next, last section, table of contents.