The Ibis API defines the functionality of the Ibis communication library; it is realized by different Ibis implementations. An Ibis object contains all administration in a single object. In fact, a JVM may run multiple Ibis instances, using different Ibis implementations, at the same time.

The user can specify the Ibis implementation to use at startup. This can be done explicitly, or by specifying the required properties of the communication channels using instances of the PortType class. Ibis then selects the best implementation to meet these requirements. When creating an Ibis implementation, a global unique name must be specified for it by the application.

## Communication

Communication is based on ReceivePorts and SendPorts of a certain PortType. A PortType can be created using the Ibis.createPortType method, where a name is given to the PortType (e.g. "satin porttype" or "RMI porttype"). Port properties are given to the PortType (for example ports are "reliable" and support "Sun serialization"). For each PortType there is a ReceivePort and a SendPort. Only ReceivePorts and SendPorts of the same PortType can communicate. Any number of ReceivePorts and SendPorts can be created on a JVM (even of the same PortType).

SendPorts and ReceivePorts are created by their PortType using the 'createSendPort' and 'createReceivePort' methods. When creating an ReceivePort that must receive by means of upcalls, it must be associated with an object that implements the "Upcall" interface. Upcalls are generated when messages arrive. The alternative is to use explicit receive to read messages.

The system provides a globally unique ReceivePortIdentifier and SendPortIdentifier for every ReceivePort and SendPort. These identifiers are implementation specific and serializable (and can be sent over the network/saved in a file etc.). When a ReceivePort is created its ReceivePortIdentifier will be stored in a registry. The application storing the ReceivePortIdentifier is responsible for providing a globally unique name (key) that identifies the ReceivePortIdentifier in the registry.

A SendPort takes the initiative to connect to or disconnect from ReceivePorts (otherwise the one-way traffic scheme is violated). A SendPort can be connected to one or more ReceivePorts using their ReceivePortIdentifiers. These ReceivePortIdentifiers may be obtained using the registry, by sending them over the network, or any other way. Additional ReceivePorts may be connected at any time. A SendPort can be disconnected from one or more ReceivePorts using their ReceivePortIdentifiers. Additional ReceivePorts may be disconnected at any time When a SendPort is no longer used it must be freed using the 'close' method. All connections the SendPort has are disconnected. When a ReceivePort is no longer used it must be freed using the 'close' method. This call will block until connections to SendPorts are disconnected (by the SendPorts).

A message can be sent from an SendPort to the set of ReceivePorts it is connected to. To do this, a Message is obtained from the SendPort (this allows streaming, as the destination is known). Data can be added to the message using "write" methods (this data may be immediately streamed to the ReceivePorts). The Message can be sent using a 'finish' method. When the 'finish' returns all data has been copied (it now may be changed) and the Message may no longer be used. When the Message arrives at a ReceivePort, how it is handled depends on whether an upcall handler was provided. If an upcall handler was provided a "new" thread is started (upcall), that runs the "upcall" method of the upcall handler. When the Message is no longer used it MAY be returned to the system using the 'finish' method (after which the message may no longer be used). If no upcall handler was provided, messages are delivered when the "receive" method is called (explicit receipt). When the Message is no longer used it MUST be returned to the system using the 'finish' method (after which the message may no longer be used). This is done to free possible resources in the underlying implementation, and to allow for new messages, as only one message per Receiveport can be active at any time.

## Ordering of Communication

Messages may export a sequence number, which can be used to determine their order. When a PortType specifies that the communication is not ordered, Message will be delivered in an undefined order. When a PortType specifies that the communication is uses some order messages will be delivered in that order.

## Adding and Removing Implementations

when an Ibis implementation is added to the pool, all other implementations will receive an upcall, providing them with the user-specified unique name of the new implementation. when an Ibis implementation wants to be removed from the pool, all other implementations will receive an upcall, providing them with the user-specified unique name of the implementation that wants to leave.

## Rationale

With ReceivePorts and SendPorts we basically have a 'connection oriented' message passing model, based on one-way connections (from Sender to Receiver).

### Why is this better than the TCP/IP model?

With our model we can support message passing (unicast and multicast), and an RPC-style model (using two one-way connections). TCP creates two-way connections and private channels, which is inappropriate for multicast.

### Why is it better than UDP or Panda?

Our model is connection oriented: when a message is created the destination is known. This allows the implementation to stream data to the destination, even while the message is being built (allowing a better bandwidth and memory utilization, and flow control with complex data structures).

Our model allows messages to be sent to an object (instead of a process). This is much better suited for the Java model (and SMP machines). Our model does not have a closed world assumption. JVMs may be added / removed during the computation.

### In general:

Our model can be implemented efficiently, both on streams based (TCP/IP) systems and message passing systems. It allows the use of low-level optimizations such as hardware multicast (or LFC). It is flexible because, using a properties mechanism, it allows the application to select and configure the provided primitives at runtime. It is extensible, because, using a properties mechanism, new functionality can be exported by implementation, without changing the interface.