2.4.2 Clients
The clients are one or more Prolog processes that have connection(s)
to the server.
To load the package, enter the query:
?- use_module(library(tipc/tipc_linda)). ?- linda_client(global). TIPC Linda server listening at: port_id('<1.1.1:3200515722>') true.
- [det]linda
- [det]linda(:Goal)
- Starts a Linda-server in this process. The network address is written to
current output stream as a TIPC
port_id/2 reference (e.g.
port_id('<1.1.1:3200515722>')
). This predicates looks to see if a server is already listening on the cluster. If so, it reports the address of the existing server. Otherwise, it registers a new server and reports its address.?- linda. TIPC Linda server now listening at: port_id('<1.1.1:3200515722>') true. ?- linda. TIPC Linda server still listening at: port_id('<1.1.1:3200515722>') true.
The following will call my_init/0 in the current module after the server is successfully started or is found already listening. my_init/0 could start client-processes, initialize the tuple space, etc.
?- linda(my_init).
- [semidet]linda_client(+Domain)
- Establishes a connection to a Linda-server providing a named tuple
space. Domain is an atom specifying a particular tuple-space,
selected from a universe of tuple-spaces. At present however, only one
tuple-space,
global
, is supported. A client may interact with any server reachable on the TIPC cluster. This predicate will fail if no server is reachable for that tuple space. - [det]close_client
- Closes the connection to the Linda-server. Causes the server to release resources associated with this client.
- [semidet]linda_timeout(?OldTime, ?NewTime)
- Controls Linda's message-passing timeout. It specifies the time window
where clients will accept server replies in response to
in
andrd
requests. Replies arriving outside of this window are silently ignored. OldTime is unified with the old timeout and then timeout is set to NewTime. NewTime is of the form Seconds:Milliseconds. A non-negative real number, seconds, is also recognized. The default is 0.250 seconds. This timeout is thread local and is not inherited from its parent. New threads are initialized to the default.Note: The synchronous behavior afforded by in/1 and rd/1 is implemented by periodically polling the server. The poll rate is set according to this timeout. Setting the timeout too small may result in substantial network traffic that is of little value.
- throws
error(feature_not_supported)
. SICStus Linda can disable the timeout by specifyingoff
as NewTime. This feature does not exist for safety reasons.
- [semidet]linda_timeout(+NewTime)
- Temporarily sets Linda's timeout. Internally, the original timeout is saved and then the timeout is set to NewTime. NewTime is as described in linda_timeout/2. The original timeout is restored automatically on cut of choice points, failure on backtracking, or uncaught exception.
- [det]out(+Tuple)
- Places a Tuple in Linda's tuple-space.
- [det]in(?Tuple)
- Atomically removes the tuple Tuple from Linda's tuple-space if it is there. The tuple will be returned to exactly one requestor. If no tuple is available, the predicate blocks until it is available (that is, someone performs an out/1).
- [semidet]in_noblock(?Tuple)
- Atomically 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.
- [det]in(+TupleList, -Tuple)
- As in/1 but succeeds when any one of the tuples in TupleList is available. Tuple is unified with the fetched tuple.
- [nondet]rd(?Tuple)
- Succeeds nondeterministically if Tuple is available in the tuple-space, suspends otherwise until it is available. Compare this with in/1: the tuple is not removed.
- [nondet]rd_noblock(?Tuple)
- Succeeds nondeterministically if Tuple is available in the tuple-space, fails otherwise. This predicate can fail due to a timeout.
- [nondet]rd(?TupleList, -Tuple)
- As in/2 but provides a choice point that does not remove any tuples.
- [nondet]bagof_in_noblock(?Template, ?Tuple, -Bag)
- [nondet]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)). true. ?- bagof_rd_noblock(C-N, x(C,N), L). L = [a-3,a-4,b-3,c-3] . true. ?- bagof_rd_noblock(C, N^x(C,N), L). L = [a,a,b,c] . true.
- [det]linda_eval(:Goal)
- [det]linda_eval(?Head, :Goal)
- [det]linda_eval_detached(:Goal)
- [det]linda_eval_detached(?Head, :Goal)
- Causes Goal to be evaluated in parallel with a parent
predicate. The child thread is a full-fledged client, possessing the
same capabilities as the parent. Upon successful completion of Goal,
unbound variables are unified and the result is sent to the Linda server
via out/1, where it is made available
to others. linda_eval/2
evaluates Goal, then unifies the result with Head,
providing a means of customizing the resulting output structure. In linda_eval/1, Head,
and
Goal are identical, except that the module name for Head
is stripped before output. If the child fails or receives an uncaught
exception, no such output occurs.
Joining Threads: Threads created using linda_eval/(1-2) are not allowed to linger. They are joined (blocking the parent, if necessary) under three conditions: backtracking on failure into an linda_eval/(1-2), receipt of an uncaught exception, and cut of choice-points. Goals are evaluated using forall/2. They are expected to provide nondeterministic behavior. That is they may succeed zero or more times on backtracking. They must however, eventually fail or succeed deterministically. Otherwise, the thread will hang, which will eventually hang the parent thread. Cutting choice points in the parent's body has the effect of joining all children created by the parent. This provides a barrier that guarantees that all child instances of Goal have run to completion before the parent proceeds. Detached threads behave as above, except that they operate independently and cannot be joined. They will continue to run while the host process continues to run.
Here is an example of a parallel quicksort:
qksort([], []). qksort([X | List], Sorted) :- partition(@>(X), List, Less, More), linda_eval(qksort(More, SortedMore)), qksort(Less, SortedLess), !, in_noblock(qksort(More, SortedMore)), append(SortedLess, [X | SortedMore], Sorted).
- [det]tuple(:Goal)
- [det]tuple(?Head, :Goal)
- registers Head as a virtual tuple in TIPC Linda's tuple
space. On success, any client on the cluster may reference the tuple, Head,
using rd/1 or rd_noblock/1.
On reference, Goal is executed by a separate thread of
execution in the host client's Prolog process. The result is unified
with Head, which is then returned to the guest client. As in
linda_eval/(1-2) above, Goal is evaluated using forall/2.
The virtual tuple is unregistered on backtracking into a tuple/(1-2),
receipt of uncaught exception, or cut of choice-points. In tuple/1,
Head and Goal are identical, except that the
module name is stripped from Head.
Note: A virtual tuple is an extension of the server. Even though it is operating in the client's Prolog environment, it is restricted in the server operations that it may perform. It is generally safe for tuple predicates to perform out/1 operations, but it is unsafe for them to perform any variant of
in
orrd
, either directly or indirectly. This restriction is however, relaxed if the server and client are operating in separate heavyweight processes (not threads) on the node or cluster. This is most easily achieved by starting a stand-alone Linda server somewhere on the cluster. See tipc_linda_server/0, below. - [nondet]tipc_linda_server
- Acts as a stand-alone Linda server. This predicate initializes the TIPC
stack and then starts a Linda server in the current thread. If a client
performs an
out(server_quit)
, the server's Prolog process will exit via halt/1. It is intended for use in scripting as follows:swipl -q -g 'use_module(library(tipc/tipc_linda)), tipc_linda_server' -t 'halt(1)'
See also manual section 2.10.2.1 Using PrologScript.
Note: Prolog will return a non-zero exit status if this predicate is executed on a cluster that already has an active server. An exit status of zero is returned on graceful shutdown.
- throws
- error(
permission_error(halt,thread,2)
,context(halt/1,Only from thread 'main')), if this predicate is executed in a thread other thanmain
.
- [semidet]tipc_initialize
- See tipc:tipc_initialize/0.
Index
- ?
- bagof_in_noblock/3
- bagof_rd_noblock/3
- close_client/0
- in/1
- in/2
- in_noblock/1
- linda/0
- linda/1
- linda_client/1
- linda_eval/1
- linda_eval/2
- linda_eval_detached/1
- linda_eval_detached/2
- linda_timeout/1
- linda_timeout/2
- out/1
- rd/1
- rd/2
- rd_noblock/1
- tipc_accept/3
- tipc_bind/3
- tipc_canonical_address/2
- tipc_close_socket/1
- tipc_connect/2
- tipc_get_name/2
- tipc_get_peer_name/2
- tipc_host_to_address/2
- tipc_initialize/0
- tipc_linda_server/0
- tipc_listen/2
- tipc_open_socket/3
- tipc_paxos_get/1
- tipc_paxos_on_change/2
- tipc_paxos_replicate/1
- tipc_paxos_set/1
- tipc_paxos_set/2
- tipc_receive/4
- tipc_send/4
- tipc_service_exists/1
- tipc_service_exists/2
- tipc_service_port_monitor/2
- tipc_service_port_monitor/3
- tipc_service_probe/1
- tipc_service_probe/2
- tipc_setopt/2
- tipc_socket/2
- tuple/1
- tuple/2