Archived

This forum has been archived. Please start a new discussion on GitHub.

Asynchronous Dispatch Interceptor

Hi,

Is it possible to make an asynchronous dispatch interceptor? I have a few components that need to be used from the "correct" thread, and an "easy" solution would be to create a dispatch interceptor, whose dispatch() is simply:
- Grab mutex
- Put Request on list
- Notify correct thread
- Release mutex
- Return DispatchAsync

The "correct" thread would then pick up the request and call ice_dispatch on the servant. This allows me to implement the code based on the output from slice2cpp --impl.

However, the Request object can't be copied, so this doesn't work :(

I've also looked at using BlobjectAsync, but I'm not quite sure how to turn the inParams into something I can call ice_dispatch() on another servant with, nor how to get the result into the outParams.

Any suggestions?

Comments

  • bernard
    bernard Jupiter, FL
    Hi Thorvald,

    I suspect you want to use Asynchronous Method Dispatch (AMD) here, i.e. on the server side:
    - the request's 'in' parameters get unmarshaled by a dispatch thread from the Ice server thread pool
    - your operation implementation just enqueues this "request": more specifically, it enqueues the in-parameters and AMD callback provided by Ice
    - the correct thread dequeues the "request" and sends back the response using the AMD callback object
    This allows me to implement the code based on the output from slice2cpp --impl.
    It's unusual when the implementation generated by slice2cpp --impl is sufficient, and this should not be a goal when using Ice!
    I've also looked at using BlobjectAsync, but I'm not quite sure how to turn the inParams into something I can call ice_dispatch() on another servant with, nor how to get the result into the outParams.

    The Blobjects are about transmitting requests without unmarshaling them, or building yourself requests dynamically, without generated code. They are useful if you're building a bridge or a router (like IceStorm or the Glacier2 router) or a new language mapping (like Ice for Python).
    You may not need this feature for Mumble.

    Cheers,
    Bernard
  • dwayne
    dwayne St. John's, Newfoundland
    Hi,

    You can take a look at the async demo in Ice 3.3 for an example of the use of AMD as Bernard mentions above.

    Dwayne
  • About slice2cpp; what I mean is that I can create a class with my slice-defined interface as parent. So if there's a
    int blipp(int blapp);
    in the slice definition, I simply override the virtual method with the same name and parameters.

    The problem with AMD is that I have quite a few methods that need to be handled this way. I'd then need to create a struct or class just to hold the input parameters, one such class for each method (as the methods have different set of parameters). Then, I'd need either a separate event-type and event list for each method, or I'd have to pass a method id and have a huge switch() statement -- in short I'd be doing marshalling and unmarshalling. And the functions I'd be calling to from the events would not be on an class that decends from the Interface, so if a new function is added to the interface, I'd get runtime errors instead of compile-time errors.

    Looking at the generated .cpp code, I see there's also a __dispatch. But IceInternal::Incoming is not copyable either (and judging from it's name, you don't want us to mess with it).. Is there a way to fake one?

    Is there no way to do this without resorting to ugly per-method hacks? I can do that, but so far my ICE code has been very neat and tidy, I'd like to keep it that way :)
  • bernard
    bernard Jupiter, FL
    Hi Thorvald,
    About slice2cpp; what I mean is that I can create a class with my slice-defined interface as parent. So if there's a
    int blipp(int blapp);
    in the slice definition, I simply override the virtual method with the same name and parameters.

    What you describe above is the usual way to implement a servant in C++: you write a C++ class that derives from the generated C++ class that corresponds to your Slice interface, and implement the pure-virtual functions that correspond to your operations. The slice2cpp--impl option generates a sample servant class; usually this generated sample does not do all you need. And usually, you don't want to use slice2cpp --impl in your Makefile since it would regenerate these files every time, and overwrite any updates in there.
    The problem with AMD is that I have quite a few methods that need to be handled this way. I'd then need to create a struct or class just to hold the input parameters, one such class for each method (as the methods have different set of parameters). Then, I'd need either a separate event-type and event list for each method, or I'd have to pass a method id and have a huge switch() statement -- in short I'd be doing marshalling and unmarshalling.

    Yes, you would need to write some code for each operation, to pass the input parameters and AMD callback to the desired thread. I am sure you could create one or more templates to streamline this code.

    Also, that's not what we call marshaling/unmarshaling: marshaling is serializing a request (or parameters) into a binary stream, and unmarshaling is the reverse. Here, you would not deal with binary streams or buffers.
    And the functions I'd be calling to from the events would not be on an class that decends from the Interface, so if a new function is added to the interface, I'd get runtime errors instead of compile-time errors.

    You would get a compile-time error if you don't provide the corresponding implementation on your servant class, since the function on the generated base class is pure-virtual.
    Looking at the generated .cpp code, I see there's also a __dispatch. But IceInternal::Incoming is not copyable either (and judging from it's name, you don't want us to mess with it).. Is there a way to fake one?

    No, there is no way to copy Request or Incoming, or you should not pass these objects from the dispatch thread to another thread.
    Is there no way to do this without resorting to ugly per-method hacks? I can do that, but so far my ICE code has been very neat and tidy, I'd like to keep it that way :)

    It's hard to say without more information. For example, if the dispatch thread was already the right thread, there would be no problem. Why do you need to use separate threads for these operations?

    Cheers,
    Bernard