Module Network.Ports

Library for distributed programming with ports. This paper contains a description of the basic ideas behind this library.

Author: Michael Hanus

Version: March 2021

Summary of exported operations:

openPort :: Port a -> [a] -> Bool  Deterministic 
Opens an internal port for communication.
send :: a -> Port a -> Bool  Deterministic 
Sends a message to a port.
doSend :: a -> Port a -> IO ()  Deterministic 
I/O action that sends a message to a port.
ping :: Int -> Port a -> IO (Maybe Int)  Deterministic 
Checks whether port p is still reachable.
timeoutOnStream :: Int -> [a] -> Maybe [a]  Deterministic 
Checks for instantiation of a stream within some amount of time.
openProcessPort :: String -> IO (Port SP_Msg)  Deterministic 
Opens a new connection to a process that executes a shell command.
openNamedPort :: String -> IO [a]  Non-deterministic 
Opens an external port with a symbolic name.
connectPortRepeat :: Int -> IO a -> Int -> String -> IO (Maybe (Port b))  Non-deterministic 
Waits for connection to an external port.
connectPortWait :: String -> IO (Port a)  Non-deterministic 
Waits for connection to an external port and return the connected port.
connectPort :: String -> IO (Port a)  Non-deterministic 
Connects to an external port.
choiceSPEP :: Port SP_Msg -> [a] -> Either String [a]  Deterministic 
This function implements a committed choice over the receiving of messages via a stream port and an external port.
newObject :: Data a => (b -> [a] -> Bool) -> b -> Port a -> Bool  Non-deterministic 
Creates a new object (of type codeState -> [msg] -> Bool/code) with an initial state and a port to which messages for this object can be sent.
newNamedObject :: (a -> [b] -> Bool) -> a -> String -> IO ()  Non-deterministic 
Creates a new object (of type codeState -> [msg] -> Bool/code) with a symbolic port name to which messages for this object can be sent.
runNamedServer :: ([a] -> IO b) -> String -> IO b  Non-deterministic 
Runs a new server (of type code[msg] -> IO a/code) on a named port to which messages can be sent.
hWaitForInputOrMsg :: a -> [b] -> IO (Either a [b])  Deterministic 
Waits until input is available on a given handles or a message in the message stream.
hWaitForInputsOrMsg :: [a] -> [b] -> IO (Either Int [b])  Deterministic 
Waits until input is available on some of the given handles or a message in the message stream.

Exported datatypes:


Port

The internal constructor for the port datatype is not visible to the user.

Constructors:


SP_Msg

A "stream port" is an adaption of the port concept to model the communication with bidirectional streams, i.e., a stream port is a port connection to a bidirectional stream (e.g., opened by openProcessPort) where the communication is performed via the following stream port messages.

Constructors:

  • SP_Put :: String -> SP_Msg : write the argument s on the output stream
  • SP_GetLine :: String -> SP_Msg : unify the argument s with the next text line of the input stream
  • SP_GetChar :: Char -> SP_Msg : unify the argument c with the next character of the input stream
  • SP_EOF :: Bool -> SP_Msg : unify the argument b with True if we are at the end of the input stream, otherwise with False
  • SP_Close :: SP_Msg : close the input/output streams

Exported operations:

openPort :: Port a -> [a] -> Bool  Deterministic 

Opens an internal port for communication.

Example call:
(openPort p s)
Parameters:
  • p : a free variable which will be constrained with the port messages
  • s : a free variable which will be instantiated to the stream of incoming messages

send :: a -> Port a -> Bool  Deterministic 

Sends a message to a port.

doSend :: a -> Port a -> IO ()  Deterministic 

I/O action that sends a message to a port.

ping :: Int -> Port a -> IO (Maybe Int)  Deterministic 

Checks whether port p is still reachable.

Example call:
(ping n p)
Parameters:
  • n : the time to wait for reachability in milliseconds
  • p : a port to be checked for reachability
Returns:
Nothing if port p is unreachable within n milliseconds, or (Just m) if port p could be contacted within m milliseconds

timeoutOnStream :: Int -> [a] -> Maybe [a]  Deterministic 

Checks for instantiation of a stream within some amount of time.

Example call:
(timeoutOnStream n str)
Parameters:
  • n : the time to wait for instantiation in milliseconds
  • str : the stream to be checked for instantiation (usually the stream of incoming messages at some port)
Returns:
(Just str) if str is instantiated within n milliseconds, or Nothing otherwise

openProcessPort :: String -> IO (Port SP_Msg)  Deterministic 

Opens a new connection to a process that executes a shell command.

Example call:
(openProcessPort cmd)
Parameters:
  • cmd : the shell command to be executed
Returns:
the output/input stream (represented as a stream port) that is connected to the standard input/output of the process performing the execution of cmd.

openNamedPort :: String -> IO [a]  Non-deterministic 

Opens an external port with a symbolic name.

Example call:
(openNamedPort portname)
Parameters:
  • portname : the symbolic name under which the port is accessible (any string without occurrences of @)
Returns:
the stream of incoming messages at this port

connectPortRepeat :: Int -> IO a -> Int -> String -> IO (Maybe (Port b))  Non-deterministic 

Waits for connection to an external port. In contrast to codeconnectPort/code, this action waits until the external port has been registered with its symbolic name.

Example call:
(connectPortRepeat waittime action retries portname)
Parameters:
  • waittime : the time to wait before retrying (in milliseconds)
  • action : I/O action to be executed before each wait cycle
  • retries : number of retries before giving up (-1 = retry forever)
  • portname : the symbolic name of the external port (must be either of the form "name@machine" or "name" where the latter is a shorthand for "name@localhost")
Returns:
Nothing (if connection is not possible within the given limits) or (Just p) where p is a port with the symbolic name portname

connectPortWait :: String -> IO (Port a)  Non-deterministic 

Waits for connection to an external port and return the connected port. This action waits (possibly forever) until the external port is registered.

Example call:
(connectPortWait portname)
Parameters:
  • portname : the symbolic name of the external port (must be either of the form "name@host" or "name" where the latter is a shorthand for "name@localhost")
Returns:
a port with the symbolic name portname

connectPort :: String -> IO (Port a)  Non-deterministic 

Connects to an external port. The external port must be already registered, otherwise an error is reported.

Example call:
(connectPort portname)
Parameters:
  • portname : the symbolic name of the external port (must be either of the form "name@host" or "name" where the latter is a shorthand for "name@localhost")
Returns:
a port with the symbolic name portname

choiceSPEP :: Port SP_Msg -> [a] -> Either String [a]  Deterministic 

This function implements a committed choice over the receiving of messages via a stream port and an external port.

EMNote that the implementation of choiceSPEP works only with Sicstus-Prolog 3.8.5 or higher (due to a bug in previous versions of Sicstus-Prolog)./EM

Example call:
(choiceSPEP sp ms)
Parameters:
  • sp : a stream port sp
  • ms : a stream of messages received via an external port
Returns:

(Left s) if s is an input line received at the stream port (via SP_GetLine) or

(Right ms) if the stream ms is instantiated
           with at least one new message at the head

newObject :: Data a => (b -> [a] -> Bool) -> b -> Port a -> Bool  Non-deterministic 

Creates a new object (of type codeState -> [msg] -> Bool/code) with an initial state and a port to which messages for this object can be sent.

Example call:
(newObject object state port)
Parameters:
  • object : an object template
  • state : the initial state of the object
  • port : a free variable which will be constrained to the port for sending messages to the object

newNamedObject :: (a -> [b] -> Bool) -> a -> String -> IO ()  Non-deterministic 

Creates a new object (of type codeState -> [msg] -> Bool/code) with a symbolic port name to which messages for this object can be sent.

Example call:
(newNamedObject object state portname)
Parameters:
  • object : an object template
  • state : the initial state of the object
  • portname : the symbolic name under which the object's port is accessible (any string without occurrences of @)

runNamedServer :: ([a] -> IO b) -> String -> IO b  Non-deterministic 

Runs a new server (of type code[msg] -> IO a/code) on a named port to which messages can be sent.

Example call:
(runNamedServer server portname)
Parameters:
  • server : a server function that processes incoming messages
  • portname : the symbolic name under which the server's port is accessible (any string without occurrences of @)

hWaitForInputOrMsg :: a -> [b] -> IO (Either a [b])  Deterministic 

Waits until input is available on a given handles or a message in the message stream. Usually, the message stream comes from an external port. Thus, this operation implements a committed choice over receiving input from an IO handle or an external port.

Note that the implementation of this operation works only with Sicstus-Prolog 3.8.5 or higher (due to a bug in previous versions of Sicstus-Prolog).

Example call:
(hWaitForInputOrMsg handle msgs)
Parameters:
  • handle : a handle for an input stream
  • msgs : a stream of messages received via an external port
Returns:
(Left handle) if the handle has some data available (Right msgs) if the stream msgs is instantiated with at least one new message at the head

hWaitForInputsOrMsg :: [a] -> [b] -> IO (Either Int [b])  Deterministic 

Waits until input is available on some of the given handles or a message in the message stream. Usually, the message stream comes from an external port. Thus, this operation implements a committed choice over receiving input from IO handles or an external port.

Note that the implementation of this operation works only with Sicstus-Prolog 3.8.5 or higher (due to a bug in previous versions of Sicstus-Prolog).

Example call:
(hWaitForInputsOrMsg handles msgs)
Parameters:
  • handles : a list of handles for input streams
  • msgs : a stream of messages received via an external port
Returns:
(Left i) if (handles!!i) has some data available (Right msgs) if the stream msgs is instantiated with at least one new message at the head