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.