Archived

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

Ice and single threaded libraries

Now I have another somewhat quirky question, where you'll likely be polite and ask me if I have a commercial need :)

Anyway Ice is completely multithreaded, which is nice and fine for most things. However other third party libraries are sometimes not thread safe, and sometimes even require that only a certian thread works on their datastructures. An example (totally random naturally) would be a 3D engine where only the engines own thread is allowed to modify the scene graph.

To a certain extent these things can be handled by using mutexes etc. to synchronise the various threads.

However for remote calls that want to modify the scenegraph, it seems necessary to buffer the incomming call, and the have the main thread resolve it in some ticked loop. This buffering will likely require the call-data to be serialised in some fashion. And since the call was already serialised when is was sent as a remote call, I was wondering if it was somehow possible to 'intercept' the Ice unmarshalling process, and buffer the call at that point, instead of having to go through a lot of unmarshaling just to serielise all the data again.

I hope I've explained the problem clearly enough.

mvh

Nis

Comments

  • mes
    mes California
    Hi,

    One way to do this is to use a thread pool having only one thread. One disadvantage to this approach is that the thread is created by Ice, therefore if you need to perform some initialization from within this thread, your application would have to delay that initialization until the first invocation.

    If that's not workable, another solution is to use AMD. You can queue up the callback objects and have them processed by a dedicated thread. However, if there are many different operations to be queued, then this can get tiresome as you would need to save all of the input parameters along with the callback object.

    Finally, you can receive the requests as blobs of bytes, as described in the Dynamic Ice chapter. This would simplify the task of queuing the requests, but dispatching them later requires you to manually unmarshal the input parameters and marshal the results. There is currently no way to receive a request as a blob and then dispatch it later using the generated code to handle the marshaling duties.

    Hope that helps,
    - Mark
  • Thanks - That was very helpful.

    It is still unclear if we really need to take this step, but if we do Dynamic Ice sounds like the most elegant solution in our perticular case (There are several different calls that it would be nice to be able to handle the same way, and on the positive side most of them don't send back any results). I'll definately have to look more at that.

    For instance it is a bit unclear to me if it is possible receive a request as a blob of bytes, even if the client called a specific function.

    Ie. the client knows a specific interface

    interface foo {
    void bar(int x);
    };

    It somehow gets a proxy of type FooPrx and invokes bar on this. Is it then possible to use Dynamic Ice, to receive this call as a simple blob of bytes server side. You seem to be doing something like this in IceStorm, where I can take a generic publisher proxy, cast it to an interface I've designed, and invoke the operations on that interface. Should I simply look at the IceStorm code to get inspiration for how this is done ?

    Also the ice_invoke operation returns a boolean, suggesting that it can't be called over one-way proxies? Or am I missing something here?

    Finally I was wondering how Dynamic Ice performs compared to regular Ice. If I use this solution of receiving requests as byteblobs, store them and handle them later, I will have to spend some time unmarshaling later. But I assume I'll that approximately the same time by not unmarshalling data when I receive it? Or ?
    mes wrote:
    There is currently no way to receive a request as a blob and then dispatch it later using the generated code to handle the marshaling duties.

    Just out of curiosity, is this a feature you might consider implementing in the future? Or that it would be reasonable for me to add myself. I guess what I'm interested in is how separated the unmarshalling and the invocation is in the autogenerated code.

    In any case, thanks for the clear reply. It seems we definately have another option if our current solution doesn't work out.
  • mes
    mes California
    Manually marshaling and unmarshaling using blobs is error-prone, since there is no indication given at compile-time if your code no longer matches the Slice definitions of the operations. For this reason, I recommend doing this only as a last resort. The "blobject" support in Ice is really provided to efficiently support services such as the Glacier2 router and IceStorm that forward requests without unmarshaling them.

    As a first step, I recommend using AMD and queuing the callback objects and input parameters, which avoids the need for any manual unmarshaling.
    For instance it is a bit unclear to me if it is possible receive a request as a blob of bytes, even if the client called a specific function.
    Yes, a "blobject" servant can receive any operation.
    Also the ice_invoke operation returns a boolean, suggesting that it can't be called over one-way proxies? Or am I missing something here?
    Oneway requests are also supported. The boolean return value indicates whether an exception was raised, but the return value is ignored for oneway requests.
    If I use this solution of receiving requests as byteblobs, store them and handle them later, I will have to spend some time unmarshaling later. But I assume I'll that approximately the same time by not unmarshalling data when I receive it?
    It will be slightly more expensive to unmarshal manually, since the Ice generated code is optimized to avoid allocations and virtual function calls where possible.

    - Mark
  • mes wrote:
    Manually marshaling and unmarshaling using blobs is error-prone, since there is no indication given at compile-time if your code no longer matches the Slice definitions of the operations. For this reason, I recommend doing this only as a last resort. The "blobject" support in Ice is really provided to efficiently support services such as the Glacier2 router and IceStorm that forward requests without unmarshaling them.

    As a first step, I recommend using AMD and queuing the callback objects and input parameters, which avoids the need for any manual unmarshaling.

    Well of course you know you system best, and I can see that this is pretty much what AMD was intended for in a way. However to queue the input parameters I would need a number of different storage classes all of which would have to be kept up to date when the slice definitions where changed, and that to me seems as atleast as big a hassle at keeping the unmarshalling up to date. Possibly this is just because I'm reasonably comfortable with unmarshalling and reflection, whereas I'm don't really know the AMD system. I'm also unsure if I need all the callback objects etc. since all the operations I need are oneway.

    By the rest of your comments it sound like Dynamic Ice could do what we want if it turns out we really need it, and reasonably efficiently at that.