object

# `linda`

Linda tuple-space implementation for process communication. Provides a server that acts as a shared blackboard where clients can write (`out/1`), read (`rd/1`), and remove (`in/1`) tuples. Uses threaded engines for the server implementation and the sockets library for network communication.

Availability:
`logtalk_load(linda(loader))`
Author: Paulo Moura
Version: 1:0:0
Date: 2026-02-26
Compilation flags:
`static, context_switching_calls, threaded`
Provides:
logtalk::message_prefix_stream/4
Uses:
list
logtalk
os
socket
Remarks:

> - Supported backends: ECLiPSe, GNU Prolog, SICStus Prolog, SWI-Prolog, and Trealla Prolog (requires both multi-threading and sockets support).

> - Linda operations: The basic operations are `out/1` (write tuple), `in/1` (remove tuple, blocking), `rd/1` (read tuple, blocking), `in_noblock/1` (remove tuple, non-blocking), and `rd_noblock/1` (read tuple, non-blocking).

> - Tuple matching: Tuples are matched using unification.

> - Blocking behavior: The `in/1` and `rd/1` predicates block until a matching tuple is available. The `in_noblock/1` and `rd_noblock/1` predicates fail immediately if no matching tuple is found.

> - Multiple clients: Multiple clients can connect to the same server. A tuple removed by `in/1` or `in_noblock/1` is only removed for one client.

> - API compatibility: The API is inspired by the SICStus Prolog Linda library.

> - Network communication: Uses TCP sockets for client-server communication, allowing processes to run on different machines.

Inherited public predicates:
(none)

## Public predicates

### `linda/0`

Starts a Linda server on an automatically assigned port. The server address (`Host:Port`) is written to the current output stream. The predicate succeeds when all clients have disconnected after a shutdown request.

Compilation flags:
`static`
Mode and number of proofs:
`linda` - `one`

### `linda/1`

Starts a Linda server with the given options. The predicate succeeds when all clients have disconnected after a shutdown request.

Compilation flags:
`static`
Template:
`linda(Options)`
Meta-predicate template:
`linda(::)`
Mode and number of proofs:
`linda(+list)` - `one`
Remarks:

> - Option `port(Port)`: Use `Port` as the server port. Must be an integer and an available port.

> - Option `Address-Goal`: `Address` is unified with `Host:Port` and `Goal` is called when the server starts. Useful for saving the address or starting clients.

> - Option `accept_hook(Client,Stream,Goal)`: When a client connects, `Client` is unified with the client address, `Stream` with the connection stream, and `Goal` is called. If `Goal` fails, the connection is rejected.

### `linda_client/1`

Connects to a Linda server at the given address (`Host:Port`).

Compilation flags:
`static`
Template:
`linda_client(Address)`
Mode and number of proofs:
`linda_client(+compound)` - `one_or_error`
Exceptions:
Already connected:
`linda_error(already_connected)`
Connection failed:
`linda_error(connection_failed(Error))`

### `close_client/0`

Closes the connection to the Linda server.

Compilation flags:
`static`
Mode and number of proofs:
`close_client` - `one`

### `shutdown_server/0`

Sends a shutdown signal to the server. The server stops accepting new connections but continues serving existing clients until they all disconnect. Call `close_client/0` after this predicate.

Compilation flags:
`static`
Mode and number of proofs:
`shutdown_server` - `one_or_error`
Exceptions:
Not connected:
`linda_error(not_connected)`

### `linda_timeout/2`

Gets or sets the client timeout. `OldTime` is unified with the current timeout and the timeout is set to `NewTime`. The timeout value is either `off` (no timeout, wait forever) or `Seconds:Milliseconds`.

Compilation flags:
`static`
Template:
`linda_timeout(OldTime,NewTime)`
Mode and number of proofs:
`linda_timeout(?compound,+compound)` - `one`

### `out/1`

Places the tuple `Tuple` in the tuple-space.

Compilation flags:
`static`
Template:
`out(Tuple)`
Mode and number of proofs:
`out(+term)` - `one`

### `in/1`

Removes a tuple matching `Tuple` from the tuple-space. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`in(Tuple)`
Mode and number of proofs:
`in(?term)` - `one`

### `in_noblock/1`

Removes a tuple matching `Tuple` from the tuple-space. Fails if no matching tuple is available.

Compilation flags:
`static`
Template:
`in_noblock(Tuple)`
Mode and number of proofs:
`in_noblock(?term)` - `zero_or_one`

### `in/2`

Removes a tuple matching one of the patterns in `TupleList` from the tuple-space. `Tuple` is unified with the matched tuple. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`in(TupleList,Tuple)`
Mode and number of proofs:
`in(+list,?term)` - `one`

### `in_list/2`

Removes a tuple matching one of the patterns in `TupleList` from the tuple-space. `Tuple` is unified with the matched tuple. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`in_list(TupleList,Tuple)`
Mode and number of proofs:
`in_list(+list,?term)` - `one`

### `rd/1`

Reads a tuple matching `Tuple` from the tuple-space without removing it. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`rd(Tuple)`
Mode and number of proofs:
`rd(?term)` - `one`

### `rd_noblock/1`

Reads a tuple matching `Tuple` from the tuple-space without removing it. Fails if no matching tuple is available.

Compilation flags:
`static`
Template:
`rd_noblock(Tuple)`
Mode and number of proofs:
`rd_noblock(?term)` - `zero_or_one`

### `rd/2`

Reads a tuple matching one of the patterns in `TupleList` from the tuple-space without removing it. `Tuple` is unified with the matched tuple. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`rd(TupleList,Tuple)`
Mode and number of proofs:
`rd(+list,?term)` - `one`

### `rd_list/2`

Reads a tuple matching one of the patterns in `TupleList` from the tuple-space without removing it. `Tuple` is unified with the matched tuple. Blocks if no matching tuple is available.

Compilation flags:
`static`
Template:
`rd_list(TupleList,Tuple)`
Mode and number of proofs:
`rd_list(+list,?term)` - `one`

### `findall_rd_noblock/3`

Returns a list of all instances of `Template` for tuples matching `Tuple` in the tuple-space. The operation is atomic.

Compilation flags:
`static`
Template:
`findall_rd_noblock(Template,Tuple,List)`
Mode and number of proofs:
`findall_rd_noblock(?term,+term,?list)` - `one`

### `findall_in_noblock/3`

Removes and returns a list of all instances of `Template` for tuples matching `Tuple` in the tuple-space. The operation is atomic - all matching tuples are removed in one synchronized operation.

Compilation flags:
`static`
Template:
`findall_in_noblock(Template,Tuple,List)`
Mode and number of proofs:
`findall_in_noblock(?term,+term,?list)` - `one`

## Protected predicates

(no local declarations; see entity ancestors if any)

## Private predicates

### `server_socket_/1`

Stores the server socket descriptor.

Compilation flags:
`dynamic`
Template:
`server_socket_(ServerSocket)`
Mode and number of proofs:
`server_socket_(?term)` - `zero_or_one`

### `client_connection_/3`

Stores active client connections. Each client has an ID, input stream, and output stream.

Compilation flags:
`dynamic`
Template:
`client_connection_(ClientId,InputStream,OutputStream)`
Mode and number of proofs:
`client_connection_(?term,?term,?term)` - `zero_or_more`

### `accept_hook_/1`

Stores the optional accept hook goal to call when a client connects.

Compilation flags:
`dynamic`
Template:
`accept_hook_(Hook)`
Mode and number of proofs:
`accept_hook_(?callable)` - `zero_or_one`

### `server_running_/0`

Flag indicating the server is running.

Compilation flags:
`dynamic`
Mode and number of proofs:
`server_running_` - `zero_or_one`

### `server_shutdown_/0`

Flag indicating the server has received a shutdown request.

Compilation flags:
`dynamic`
Mode and number of proofs:
`server_shutdown_` - `zero_or_one`

### `tuple_/1`

Stores tuples in the Linda tuple space.

Compilation flags:
`dynamic`
Template:
`tuple_(Tuple)`
Mode and number of proofs:
`tuple_(?term)` - `zero_or_more`

### `waiting_/3`

Stores blocked clients waiting for tuples. Records the client ID, request pattern, and output stream.

Compilation flags:
`dynamic`
Template:
`waiting_(ClientId,Request,OutputStream)`
Mode and number of proofs:
`waiting_(?term,?term,?term)` - `zero_or_more`

### `engine_counter_/1`

Counter for generating unique client engine names.

Compilation flags:
`dynamic`
Template:
`engine_counter_(Counter)`
Mode and number of proofs:
`engine_counter_(?integer)` - `zero_or_one`

### `client_engine_/2`

Maps client IDs to their corresponding threaded engine names.

Compilation flags:
`dynamic`
Template:
`client_engine_(ClientId,EngineName)`
Mode and number of proofs:
`client_engine_(?term,?atom)` - `zero_or_more`

### `client_connection_input_/1`

Stores the input stream for the client connection to the server.

Compilation flags:
`dynamic`
Template:
`client_connection_input_(InputStream)`
Mode and number of proofs:
`client_connection_input_(?term)` - `zero_or_one`

### `client_connection_output_/1`

Stores the output stream for the client connection to the server.

Compilation flags:
`dynamic`
Template:
`client_connection_output_(OutputStream)`
Mode and number of proofs:
`client_connection_output_(?term)` - `zero_or_one`

### `client_timeout_/1`

Stores the timeout value for blocking client operations. Value is either `off` or `Seconds:Milliseconds`.

Compilation flags:
`dynamic`
Template:
`client_timeout_(Timeout)`
Mode and number of proofs:
`client_timeout_(?compound)` - `zero_or_one`

### `ts_out/1`

Synchronized predicate to add a tuple to the tuple space and wake waiting clients.

Compilation flags:
`static, synchronized`
Template:
`ts_out(Tuple)`
Mode and number of proofs:
`ts_out(+term)` - `one`

### `ts_in/4`

Synchronized predicate to remove a matching tuple or register a waiting client.

Compilation flags:
`static, synchronized`
Template:
`ts_in(Tuple,ClientId,OutputStream,Found)`
Mode and number of proofs:
`ts_in(+term,+term,+term,-compound)` - `one`

### `ts_in_noblock/2`

Synchronized predicate to try removing a matching tuple without blocking.

Compilation flags:
`static, synchronized`
Template:
`ts_in_noblock(Tuple,Found)`
Mode and number of proofs:
`ts_in_noblock(+term,-compound)` - `zero_or_one`

### `ts_in_list/4`

Synchronized predicate to remove a tuple matching one of multiple patterns or register a waiting client.

Compilation flags:
`static, synchronized`
Template:
`ts_in_list(TupleList,ClientId,OutputStream,Found)`
Mode and number of proofs:
`ts_in_list(+list,+term,+term,-compound)` - `one`

### `ts_rd/4`

Synchronized predicate to read a matching tuple or register a waiting client.

Compilation flags:
`static, synchronized`
Template:
`ts_rd(Tuple,ClientId,OutputStream,Found)`
Mode and number of proofs:
`ts_rd(+term,+term,+term,-compound)` - `one`

### `ts_rd_noblock/2`

Synchronized predicate to try reading a matching tuple without blocking.

Compilation flags:
`static, synchronized`
Template:
`ts_rd_noblock(Tuple,Found)`
Mode and number of proofs:
`ts_rd_noblock(+term,-compound)` - `zero_or_one`

### `ts_rd_list/4`

Synchronized predicate to read a tuple matching one of multiple patterns or register a waiting client.

Compilation flags:
`static, synchronized`
Template:
`ts_rd_list(TupleList,ClientId,OutputStream,Found)`
Mode and number of proofs:
`ts_rd_list(+list,+term,+term,-compound)` - `one`

### `ts_findall_rd_noblock/3`

Synchronized predicate to collect all tuples matching a pattern.

Compilation flags:
`static, synchronized`
Template:
`ts_findall_rd_noblock(Template,Tuple,List)`
Mode and number of proofs:
`ts_findall_rd_noblock(+term,+term,-list)` - `zero_or_more`

### `ts_findall_in_noblock/3`

Synchronized predicate to collect and remove all tuples matching a pattern.

Compilation flags:
`static, synchronized`
Template:
`ts_findall_in_noblock(Template,Tuple,List)`
Mode and number of proofs:
`ts_findall_in_noblock(+term,+term,-list)` - `zero_or_more`

## Operators

(none)