It is a rather often occuring constellation that polymake script must simultaneously communicate with several processes running in parallel. These can be clients, external programs like nauty or TOPCOM, or interactive visualizers like JavaView. Without special precautions the parallel communication inavoidably leads to mutual blocking (deadlocks).

There is a family of related classes helping to solve this kind of problems. The base class is Poly::Pipe. It should used as a wrapper around all I/O handles connected to external processes:

open HANDLE, ...; new Poly::Pipe(\*HANDLE); open my ; new Poly::Pipe();

The Poly::Pipe constructor takes an I/O handle or a reference to a handle and ties a special object to it. Then all reading and writing operations on the handle are protected against unexpected blocking.

In the most of cases you won't use this class directly, but one of its derivatives.

Filter-like programs

Filters are programs reading from stdin and writing to stdout, like the standard UNIX sort. The class Poly::ProgramPipe must be used to communicate with them:

$p=new Poly::ProgramPipe "program", "arg", ... ;

Launches the program. Initially the object $p is in output mode. After the whole output has been sent to the program, the first reading operation toggles it to the input mode:

print $p ...; ... while (<$p>) { ... } ... close $p;

Note that the external program is expected to set the correct exit code, namely 0 for success. Any nonzero exit code will raise an exception when closing the pipe.

Interactive programs

Interactive programs require asynchronous communication; both sides (polymake and the external program) can act as initiators of the data interchage. The best suited communication mechanism for these is an old good TCP socket. There are wrapper classes for both client and server side sockets.

$s=new Poly::ServerSocket($port); # or $s=new Poly::ServerSocket; $port=$s->port; $p=$s->accept;

A wrapper for the server side socket. It can either be bound to a fixed port number or choose a free port by itself, in both cases at the local loopback IP address 127.0.0.1. $p returned by accept is a Poly::Pipe object.

$p=new Poly::ClientSocket($hostname, $port);

A wrapper for the client side socket.

Client programs

Although clients are from the logical point of view nothing else as special subroutines for polymake script, technically they are still separate executables running in parallel processes. Since the client programs are using their own communication protocol, they must be started via special function client, but never with system:

Modules::client("client_name", argument, ...);

Each command line argument must be passed as a separate expression, even the option keywords and values like -seed 1 must not be glued together. There are special rules about the client arguments:

  1. On the position for file arguments you must pass Poly::Object's (e.g. $this in a production rule or user method.)
  2. On the position for the output file argument, if any, you must pass an empty object (without properties) created by the explicit constructor call, e.g. new Apps::polytope::RationalPolytope() .
  3. On the positions for property names you may pass array references, even if they are not pointing to any object's property. They can be used for both input to and output from the client. In the earlier polymake versions they were called "scratch sections". If all the data passed to the client is of this temporary nature, you don't need to invent an artificial object, but can give undef as the file argument.

The client must terminate with exit code 0 (success), otherwise an exception is raised.

The objects created by clients are not automatically saved after the session end unless you take care of this. If you want to store an object in a file, you must either do it explicitly:

$p=new OBJECT_TYPE; Modules::client("CLIENT_NAME", $p, args...); $p->commit; ... $p->save("FILENAME");
The object is saved immediately in the file FILENAME or FILENAME.DEFAULT_SUFFIX if no suffix was specified.

or assign a name to the object during the creation:

$p=new OBJECT_TYPE("NAME"); Modules::client("CLIENT_NAME", $p, args...); $p->commit;
The object will be saved when destroyed (at the latest at the program termination) in the file NAME.DEFAULT_SUFFIX .

Note the obligatory call to the commit method in both cases.