Introduction
============

Ice-E is a compact subset of Ice designed for embedded environments
while retaining many of the features that have made Ice such a
compelling alternative for distributed applications.


Comparing Ice-E and Ice
=======================

In order to reduce the size of the Ice-E run time, several Ice
features have been removed, and others are optional. The differences
are discussed in the sections below.

Concurrency Models
------------------

Ice-E supports only the thread-per-connection server-side concurrency
model; the thread pool concurrency model is not supported.

Applications that make nested callbacks must be aware of the following
limitations of the thread-per-connection model:

* For bidirectional connections, the nested callback must be a oneway
  invocation.

* For regular (unidirectional) connections, the nested callback can
  be a twoway invocation.

* Only one level of nested callbacks is allowed.

For the client-side, Ice-E supports the thread-per-connection model as
well as a blocking concurrency model that can provide better
performance results. Set the configuration property Ice.Blocking=1 to
enable the blocking model. In addition to the limitations of the
thread-per-connection model described above, the blocking model also
disallows the use of bidirectional connections.

Transports
----------

Ice-E includes support for the TCP transport; UDP and SSL are not
supported. The built-in TCP transport can be replaced with one of your
own.

Objects by Value
----------------

Ice-E does not allow Slice classes to be transmitted by value,
although it is still possible to use Slice classes in a local context.

Servant Locators
----------------

Ice-E does not support servant locators. Ice-E applications must
use the active servant map.

Collocation Optimization
------------------------

Support for collocation optimization has been removed. Note that
Ice-E applications are still able to make invocations on collocated
servants, but those invocations are not optimized and therefore will
be marshaled and sent over the built-in transport.

Other Removed Features
----------------------

Ice-E has also eliminated the following features:

* Asynchronous invocation and dispatch
* Streaming APIs
* Active connection management
* Protocol compression
* Ice::Application and Ice::Service classes

Optional Features
-----------------

Support for routers, locators and batch messages is enabled by
default but can be removed in order to further reduce the size of
the Ice-E run time. See the "Configuration" section below for more
information.

Compatibility
-------------

Ice-E and Ice share the same C++ mapping and remain source-code
compatible, given the limitations described above. Furthermore,
since the two products also share the same protocol, a distributed
system can use any combination of Ice and Ice-E applications.

Customization
-------------

If the current features do not meet your requirements, ZeroC can
customize Ice-E for commercial users. Please contact us at
info@zeroc.com for more information.


Run-time Libraries
==================

In order to minimize the size of Ice-E applications, two versions of
the run time library are provided:

* The "client" library is suitable for applications requiring only
  client-side functionality.

* The "server" library supports client- and server-side functionality.

A simple rule of thumb is to use the server library if your program
creates an object adapter, otherwise you can use the client library.

Users of the client library must define the preprocessor macro
ICEE_PURE_CLIENT when compiling an application as well as link with
the appropriate run time library.


Configuration
=============

You may build the Ice-E run time libraries with certain components
disabled in order to further reduce the size of your applications. The
default configuration enables all of the optional components, but you
can selectively disable them by editing the file include/IceE/Config.h
and commenting out their corresponding preprocessor macros. The
optional components are described below. For more information on these
features, please refer to the Ice manual.

Router Support
--------------

If ICEE_HAS_ROUTER is defined, the Ice-E libraries will include
support for routers. This component is necessary in order to use
Ice-E with the Glacier2 router.

Applications that use routers often also receive callbacks from remote
servers. These applications must use the server library, because the
client library does not provide support for callbacks.

Locator Support
---------------

If ICEE_HAS_LOCATOR is defined, the Ice-E libraries will include
support for locators. This component is necessary in order to use
indirect proxies in Ice-E.

Batch Messages Support
----------------------

If ICEE_HAS_BATCH is defined, the Ice-E client library will include
support for sending batch messages. This feature cannot be disabled
in the server library.

Blocking Client Support
-----------------------

If ICEE_PURE_BLOCKING_CLIENT is defined, the Ice-E client library will
include support only for the blocking client-side concurrency model. 


Alternate Sequence Mapping
==========================

Slice sequences map to std::vector by default, but it is possible to
change this mapping using metadata. Any user-defined class can be used
as the sequence type as long as it conforms to the following
constraints:

 * has a default constructor
 * has a copy constructor
 * has a constructor that takes the initial size of the sequence as a
   parameter
 * implements size() to return the current sequence size
 * implements swap() to swap contents with another class of the same
   type
 * has an iterator and const_iterator and implements begin() and end()
 * is responsible for its own memory management

In addition to std::vector, the templates std::list and std::deque
conform to the constraints above and can also be used.

The following syntax should be used to specify an alternate mapping
for a Slice sequence:

["cpp:type:std::deque< ::Ice::Byte>"] sequence<byte> ByteSeq;

This metadata will cause std::deque to be used for all occurrences of
ByteSeq in your Slice definitions. You can also define an alternate
sequence mapping for specific occurrences of a sequence type, such as
an operation parameter or the data member of a struct, using the
syntax shown below:

sequence<byte> ByteSeq; // Uses the default mapping to std::vector.

struct S
{
    // This member uses the default mapping.
    ByteSeq seq1;

    // Modify the mapping for this data member.
    ["cpp:type:std::list< ::Ice::Byte>"] ByteSeq seq2;
};

interface I
{
    // Modify the mapping of the return value and the parameter.
    ["cpp:type:list< ::Ice::Byte>"]
    ByteSeq op(["cpp:type:list< ::Ice::Byte>"] ByteSeq seq);
};

Two additional metadata directives are supported for the input
parameters of an operation. The "array" directive maps a sequence to
a pair of pointers to the element type as [first, last). Consider
this example:

interface I
{
    void op(["cpp:array"] ByteSeq seq);
};

The signature of the servant's method is mapped as follows:

void op(std::pair<const Ice::Byte*, const Ice::Byte*>, ...)

For byte sequences, these pointers refer to memory in the Ice run
time's internal buffers, which avoids the overhead of an extra copy
on the server side.

The "range" directive maps a sequence to a pair of const_iterators
that point to the beginning and end of the sequence. For example:

interface I
{
    void op(["cpp:range"] ByteSeq seq);
};

The signature of the servant's method is mapped as follows:

void op(std::pair<ByteSeq::const_iterator, ByteSeq::const_iterator>, ...)

The range directive accepts an optional argument specifying an
alternate sequence type, as shown in this example:

interface I
{
    void op(["cpp:range:std::deque< ::Ice::Byte>"] ByteSeq seq);
};

The signature of the servant's method is mapped as follows:

void op(std::pair<std::deque< ::Ice::Byte>::const_iterator,
		  std::deque< ::Ice::Byte>::const_iterator>, ...)

Finally, when using an alternate sequence mapping, it is usually
necessary for the generated header file to include a file that
defines the alternate type. You can force the inclusion of one
or more files using global metadata.

For example, if you make use of std::list and std::deque as
alternate sequence mappings, you would need to add the following
metadata to the beginning of your Slice file:

[["cpp:include:deque", "cpp:include:list"]]

The code example in the test/IceE/custom subdirectory demonstrates
the use of alternate sequence mappings.


Installation
============

For installation instructions, please refer to the INSTALL.* file for
your platform.
