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:

C++
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:

C++
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:

C++
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:

C++
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:

C++
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:

C++
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:

C++
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.

See Also