Module espace_cli

Low level access functions for the tuple space.

Copyright © 2023, Fred Youhanaie

Authors: Fred Youhanaie (fyrlang@anydata.co.uk).

Description

Low level access functions for the tuple space.

These are the functions that directly access the espace tables. They replace the original gen_server based access methods.

The functions in this module are expected to be called from within other espace modules.

Function Index

add_pattern/4*add a pattern for a waiting client.
add_tuple/2add a Tuple to the tuple space.
check_match/5*Search for a pattern and return the matching tuple.
check_tuple/3*Check Tuple against the patterns currently being waited for by in or rd clients.
check_waitlist/2*Start the scan of the table of clients waiting for Tuple.
get_tuple/3perform a data input operation.

Function Details

add_pattern/4 *

add_pattern(Inst_name::atom(), Cli_ref::reference(), Pattern::tuple(), Cli_pid::pid()) -> true

add a pattern for a waiting client.

For each blocking client, we keep a unique reference, the pattern being blocked on, and the client pid.

add_tuple/2

add_tuple(Inst_name::atom(), Tuple::tuple()) -> done

add a Tuple to the tuple space.

This function implements the out operation. It is also called at the end of an eval operation.

Once the Tuple is added to the tuple space, the patterns table is searched for any clients waiting for such a tuple. The search is performed in a separate concurrent process, so that the calling client process can continue with its own tasks.

check_match/5 *

check_match(Inst_name::atom(), Espace_op::in | rd | inp | rdp, Pattern::tuple(), Tab_id::ets:tid(), X5::'$end_of_table' | term()) -> {nomatch} | {nomatch, reference()} | {match, {list(), tuple()}}

Search for a pattern and return the matching tuple.

We first look for a match and if a match is found, we get the entire record. Since multiple processes may be actively looking for the same tuple, we make sure that the same tuple cannot be taken (in or inp) by more than one process.

If a matching tuple is not found, we either block or return nomatch, depending on the type of the operation.

check_tuple/3 *

check_tuple(Tuple::tuple(), Tab_id::ets:tid(), Key::'$end_of_table' | integer()) -> done

Check Tuple against the patterns currently being waited for by in or rd clients.

The whole patterns (tspatt) table is scanned sequentially. As matching patterns are found, the corresponding client is notified to retry the in or rd operation.

It is possible that more than one process may be scanning for the same target pattern. However, only one of them will notify the client, which will be the first process to successfully take the ETS record from the patterns table.

Each record in the table is accessed 2-3 times:

  1. During the first/next scan.
  2. The lookup just before the test for match
  3. The removal of the tuple when there is a match
The table may be scanned concurrently by multiple independent processes. While each of the above operations are atomic, we need the whole sequence to "appear" atomic to the client. The tuple will only be removed and the client notified if the removal is successful. That is, the first scanner that manages to remove the tuple

check_waitlist/2 *

check_waitlist(Inst_name::atom(), Tuple::tuple()) -> done

Start the scan of the table of clients waiting for Tuple.

get_tuple/3

get_tuple(Inst_name::atom(), Espace_op::in | rd | inp | rdp, Pattern::tuple()) -> {nomatch} | {nomatch, reference()} | {match, {list(), tuple()}}

perform a data input operation.

Performs one of the in, rd, inp or rdp operations.

Multiple processes may access the ETS table concurrently, and even "compete" for the same tuple. We will ensure that in the case of in and inp only one of them will succeed in taking the tuple.

If a match is found we retrun {match, {list(), tuple()}}, where the list() will contain the $N fields in Pattern, and the tuple() is the entire matched tuple record. If match is not found, we return {nomatch} for inp and rdp, and {nomatch, reference()} for in and rd. For the latter the calling process should wait/block for two types of messages {reference(), retry,} and {reference(), quit}. These messages are handled in the espace module.


Generated by EDoc