Communicator Initialization and Destruction
3 min read
2 min read
2 min read
2 min read
2 min read
2 min read
2 min read
2 min read
Creating a Communicator
In C++, you create a communicator by calling the C++ function Ice::initialize, for example:
intmain(int argc, char* argv[]){ Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv); // ...}initialize accepts a C++ reference to argc and an argument vector argv. The function scans the argument vector for any command-line options that are relevant to the Ice runtime; any such options are removed from the argument vector so, when initialize returns, the only options and arguments remaining are those that concern your application. If anything goes wrong during initialization, initialize throws an exception.
When you're done with a communicator, call destroy on it. destroy destroys the communicator's object adapters, closes its outgoing connections, and waits for all outstanding dispatches to complete before returning.
An Ice::CommunicatorHolder destroys the communicator it holds when it goes out of scope, including when the application throws an exception:
#include <Ice/Ice.h>
intmain(int argc, char* argv[]){ try { Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv); Ice::CommunicatorHolder communicatorHolder{communicator};
// ... application code ... } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return 1; } return 0;}Explicit Lifetime Management
Without a CommunicatorHolder, your application calls destroy in every path, including when it throws an exception:
Ice::CommunicatorPtr communicator = Ice::initialize(argc, argv);try{ // ... application code ...}catch (...){ communicator->destroy(); throw;}communicator->destroy();To take over the destruction of a communicator that a CommunicatorHolder holds, call release: it returns the communicator and empties the holder, whose destructor then no longer destroys it.
You create a communicator by using its constructor, for example:
await using var communicator = new Ice.Communicator(ref args);Ice.Communicator constructor accepts the argument vector that is passed to Main by the operating system. The method scans the argument vector for any command-line options that are relevant to the Ice runtime; any such options are removed from the argument vector so, when Ice.Communicator constructor returns, the only options and arguments remaining are those that concern your application. If anything goes wrong during initialization, it throws an exception.
Ice.Communicator implements both IDisposable and IAsyncDisposable. This allows you to create and cleanup your communicator with await using in async applications (as shown above). In synchronous code, you can use instead:
// In synchronous code.using var communicator = new Ice.Communicator(ref args);You create a communicator by using its constructor, for example:
class Client { public static void main(String[] args) { try (Communicator communicator = new Communicator(args)) { ... } }}The constructor accepts the argument vector that is passed to main by the operating system. The constructor scans the argument vector for any command-line options that are relevant to the Ice runtime; if anything goes wrong during initialization, it throws an exception. The constructor leaves args unchanged; to get the arguments that remain once the Ice options are removed, call the constructor that also accepts a List<String> remainingArgs, which it fills with these arguments.
Communicator implements AutoCloseable. This allows you to create and cleanup your communicator in a try-with-resources statement as shown above.
You create a communicator by using its constructor for example:
import { Ice } from "@zeroc/ice";
await using communicator = new Ice.Communicator(process.argv);This constructor accepts the argument vector. It scans the argument vector for any command-line options that are relevant to the Ice runtime; any such options are removed from the argument vector so, when the constructor returns, the only options and arguments remaining are those that concern your application. If anything goes wrong during initialization, it throws an exception.
In a browser application, you should call the constructor without the argument vector.
Communicator implements the asyncDispose method. This allows you to create and cleanup your communicator with await using as shown above.
You create a communicator with the Ice.Communicator constructor:
communicator = Ice.Communicator(args);The constructor accepts an argument vector and parses the command-line options that are relevant to the Ice runtime into the properties of the new communicator. If anything goes wrong during initialization, it throws an exception. The constructor also accepts the Properties and SliceLoader name-value arguments; when you pass both an argument vector and Properties, the Ice options in the argument vector override these properties.
The constructor leaves args unchanged. To get the arguments that remain once the Ice options are removed, create the properties yourself and pass them to the constructor:
[props, remArgs] = Ice.Properties(args);communicator = Ice.Communicator(Properties = props);To destroy the communicator when the function that created it returns, schedule the call to destroy with onCleanup:
cleanup = onCleanup(@() communicator.destroy());MATLAB clears cleanup when the function returns, which calls destroy on the communicator. The destroy method is responsible for cleaning up the communicator: it closes network connections and reclaims operating system resources, such as file descriptors and memory.
You create a communicator by calling Ice\initialize, for example:
<?phprequire_once 'Ice.php';
$communicator = Ice\initialize();...?>In PHP, unlike other languages, you do not need to destroy the communicator: when a PHP request completes, Ice for PHP destroys every communicator that the request created and did not register.
You create a communicator by using its constructor, for example:
import Iceimport sys
def main(): with Ice.Communicator(sys.argv) as communicator: ...Ice.Communicator constructor accepts the argument list that is passed to the program by the operating system. The constructor scans the argument list for any command-line options that are relevant to the Ice runtime; any such options are removed from the argument list so, when Ice.Communicator constructor returns, the only options and arguments remaining are those that concern your application. If anything goes wrong during initialization, it raises an exception.
Communicator implements the Python context manager protocol, which cleans up the communicator automatically at the end of the with block.
async with is preferred in an async context. For example:
import Iceimport asyncioimport sys
async def main(): async with Ice.Communicator( sys.argv, eventLoop=asyncio.get_running_loop()) as communicator: ...You create a communicator by calling Ice::initialize, for example:
require 'Ice'
Ice.initialize(ARGV) do |communicator| ...endIce.initialize accepts the argument list that is passed to the program by the operating system. The function scans the argument list for any command-line options that are relevant to the Ice runtime; any such options are removed from the argument list so, when Ice.initialize returns, the only options and arguments remaining are those that concern your application. If anything goes wrong during initialization, initialize raises an exception.
This syntax ensures the communicator is destroyed when the block completes. The destroy method is responsible for cleaning up the communicator. In particular, destroy ensures that any outstanding threads started by the underlying Ice C++ communicator are joined with and reclaims a number of operating system resources, such as file descriptors and memory. Never allow your program to terminate without calling destroy first.
The initialize block accepts a single argument, the communicator.
You create a communicator by calling Ice.initialize, for example:
let communicator = try Ice.initialize(CommandLine.arguments)initialize scans the argument array for any command-line options that are relevant to the Ice runtime. If anything goes wrong during initialization, initialize throws an exception.
Once you no longer need a Communicator, you must call destroy on this Communicator. The destroy method is responsible for cleaning up the communicator. In particular, in an Ice server, destroy waits for operation implementations that are still executing to complete. In addition, destroy ensures that any outstanding threads are joined with and reclaims a number of operating system resources, such as file descriptors and memory. Never allow your application to terminate without calling destroy first.
The general shape of a simple command-line Swift application becomes:
let communicator = try Ice.initialize(CommandLine.arguments)defer { communicator.destroy()}Initialization Data
When a communicator is created, its constructor or the initialize method configures several features that control its behavior. Once set, these features remain in effect for the lifetime of the communicator and cannot be changed afterward. Therefore, any customization of these features must be done at communicator creation time.
The InitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationDataInitializationData class or struct holds all the features (or options) that you can customize when you create a communicator.