Asynchronous Dynamic Invocation and Dispatch in C++
This page describes the asynchronous C++ mapping for the ice_invoke proxy function and the Blobject class.
On this page:
Calling ice_invoke Asynchronously in C++
The asynchronous mapping for ice_invoke resembles that of the static AMI mapping. Multiple overloadings are provided to support the use of callbacks, request contexts, and zero-copy semantics. The return value and the parameters operation, mode, and inParams have the same semantics as for the synchronous version of ice_invoke.
Basic Asynchronous Mapping for ice_invoke in C++
The basic mapping is shown below:
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams,
const Ice::Context& __ctx);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams,
const Ice::Context& __ctx,
const Ice::LocalObjectPtr& __cookie = 0);
bool end_ice_invoke(std::vector<Ice::Byte>&, const Ice::AsyncResultPtr&);
User exceptions are handled differently than for static asynchronous invocations. Calling end_ice_invoke can raise system exceptions but never raises user exceptions. Instead, the boolean return value of end_ice_invoke indicates whether the operation completed successfully (true) or raised a user exception (false). If the return value is true, the byte sequence contains an encapsulation of the results; otherwise, the byte sequence contains an encapsulation of the user exception.
Generic Asynchronous Callback Mapping for ice_invoke in C++
The generic callback API is also available:
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams,
const Ice::CallbackPtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams,
const Ice::Context& __ctx,
const Ice::CallbackPtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams,
const Ice::CallbackPtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams,
const Ice::Context& __ctx,
const Ice::CallbackPtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Use the Ice::newCallback function to create callback objects, as shown in the static AMI mapping.
Type-Safe Asynchronous Callback Mapping for ice_invoke in C++
The type-safe callback API looks as follows:
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams,
const Ice::Callback_Object_ice_invokePtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::vector<Ice::Byte>& inParams,
const Ice::Context& __ctx,
const Ice::Callback_Object_ice_invokePtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams,
const Ice::Callback_Object_ice_invokePtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Ice::AsyncResultPtr begin_ice_invoke(
const std::string& operation,
Ice::OperationMode mode,
const std::pair<const Ice::Byte*, const Ice::Byte*>& inParams,
const Ice::Context& __ctx,
const Ice::Callback_Object_ice_invokePtr& __del,
const Ice::LocalObjectPtr& __cookie = 0);
Several overloadings of Ice::newCallback_Object_ice_invoke allow you to create callback objects. Versions are provided to support zero-copy semantics for the byte sequence containing the operation's results, as well as a cookie value whose type is inferred and represented here by the CT symbol:
template<class T> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*cb)(bool, const std::vector<Ice::Byte>&),
void (T::*excb)(const ::Ice::Exception&),
void (T::*sentcb)(bool) = 0);
template<class T> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*cb)(bool, const std::pair<const Byte*, const Byte*>&),
void (T::*excb)(const ::Ice::Exception&),
void (T::*sentcb)(bool) = 0);
template<class T, typename CT> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*cb)(bool, const std::vector<Ice::Byte>&, const CT&),
void (T::*excb)(const ::Ice::Exception&, const CT&),
void (T::*sentcb)(bool, const CT&) = 0);
template<class T, typename CT> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*cb)(bool, const std::pair<const Byte*, const Byte*>&,
const CT&),
void (T::*excb)(const ::Ice::Exception&, const CT&),
void (T::*sentcb)(bool, const CT&) = 0);
template<class T> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*excb)(const ::Ice::Exception&),
void (T::*sentcb)(bool) = 0);
template<class T, typename CT> Callback_Object_ice_invokePtr
newCallback_Object_ice_invoke(const IceUtil::Handle<T>& instance,
void (T::*excb)(const ::Ice::Exception&, const CT&),
void (T::*sentcb)(bool, const CT&) = 0);
Subclassing BlobjectAsync in C++
BlobjectAsync is the name of the asynchronous counterpart to Blobject:
namespace Ice {
class BlobjectAsync : virtual public Ice::Object {
public:
virtual void ice_invoke_async(
const AMD_Object_ice_invokePtr& cb,
const std::vector<Ice::Byte>& inParams,
const Ice::Current& current) = 0;
};
}
To implement asynchronous dynamic dispatch, a server must subclass BlobjectAsync and override ice_invoke_async.
The first argument to the servant's member function is a callback object of type Ice::AMD_Object_ice_invoke, shown here:
namespace Ice {
class AMD_Object_ice_invoke : ... {
public:
virtual void ice_response(
bool result,
const std::vector<Ice::Byte>& outParams) = 0;
virtual void ice_response(
bool result,
const std::pair<const Ice::Byte*, const Ice::Byte*>& outParams) = 0;
virtual void ice_exception(const std::exception&) = 0;
virtual void ice_exception() = 0;
};
}
Upon a successful invocation, the servant must invoke one of the ice_response methods on the callback object, passing true as the first argument and encoding the encapsulated operation results into outParams. To report a user exception, the servant invokes ice_response with false as the first argument and the encapsulated form of the exception in outParams. Note that the second overloading of ice_response uses the array mapping (see the next section below).
ice_exception has several overloadings. Note however that in the dynamic dispatch model, the ice_exception function must not be used to report user exceptions; doing so results in the caller receiving UnknownUserException.
Subclassing BlobjectArrayAsync in C++
To implement an asynchronous Blobject servant that uses the array mapping, derive your implementation class from Ice::BlobjectArrayAsync and override the ice_invoke_async function:
class BlobjectArrayAsync : virtual public Ice::Object {
public:
virtual void ice_invoke_async(
const AMD_Object_ice_invokePtr& cb,
const std::pair<const Ice::Byte*, const Ice::Byte*>& in,
const Ice::Current& current) = 0;
};
As shown in the previous section, the AMD callback class provides an overloaded ice_response method that supports the array mapping for the encoded out parameter blob.
The discussion of sequences provides more information on the array mapping.