Boost logo

Boost :

Subject: Re: [boost] Interest in Remote Procedure Call Library?
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2010-02-07 11:30:59


Mirror looks interesting and for some reason never showed up on my google searches! After reading the documentation it was unclear to me how one would use the "mirrored" interface other than to query the text description of the interface component types/names. For example, there was no abstract (virtual) way of invoking a method either using boost::any, void*, or serialized parameters. Perhaps I missed it. It also appears that Mirror requires C++0x which limits its application.

With respect to exceptions, that is certainly supported. The code below would work "as expected" and the "divide by zero" exception would be marshaled back.

RemoteInterface<SomeClass> ri("my.named.service");

try {
        float rtn = ri.divide( 5, 0 );
} catch ( const std::exception& e )
{
        ..
}

The asynchronous interface would be:

future<float> rtn = ri.divide( 5, 0, AsyncFlag );
ri.divide( 5, 0, AsyncFlag | NoReturn );
future<float> rtn2 = ri.divide( 5, 0, AsyncFlag );

try {
if( !rtn.wait(timeout) ) { err...timeout }
} catch ( const std::exception& e ) { divide by zero caught async }

float auto_cast = rtn2;

Earlier versions of the library used a meta-object system similar to mirror and I ended up with "slow" code that looked something like:

ri.invoke( "float divide(float,float)", 5, 0 );

That approach was error prone (no compile time checks on signature). So I replaced it with:

ri.invoke( SLOT(SomeClass,divide), 5, 0 );

But I realized I was providing all of the compile time information necessary to optimize the serialization yet the implementation was still
dependent upon polymorphic functions dealing with "generic" parameters. Plus, my ultimate goal was to make using the remote object
as seamless/similar to using the local object as possible. Thus what I really needed was the concept of a "proxy" object that provided
all of the same methods as the "real object" and then provided a means to "delegate" the actual invocation of those methods.

You will notice that whether it is dbus, corba, etc they all have the fundamental layer that looks something like:

ri.invoke( "float divide(float,float)", 5, 0 );

And then they use code generation or manual implementation to create a "proxy class" that has real methods that then invoke the fundamental layer to hide the
messy invocation details from the user of the remote object.

The META_INTERFACE(...) macro defines a generic "Proxy Template" that can then be specialized for different kinds of back-ends via a delegate template parameter.

template<typename SomeClass, typename SomeDelegate=DefaultDelegate>
MetaInterface : ...

The default delegate simply takes a pointer to the "real object" and would enable local scripting engines or the server side of a RPC library.

The RemoteInterfaceDelegate replaces the call to the "real object" with a remote procedure call using your "protocol of choice". You would have a different RemoteInterfaceDelegate
for XML-RPC, Corba, dbus... etc

In reality what I believe I have achieved is automatic generation of proxy classes without the use of an "interface description language", "Qt moc compiler", or other code generation schemes outside of standard C++. With this auto-generation the "fundamental layer" gets full access to all of the type info and thus can implement very efficient in-line serialization/deserialization of parameters and return values.

Obviously, the library will need a lot of work to fit with boost naming conventions and I will need some help with macros to auto-define all combinations of parameters (currently 0-8 are supported, but manually defined).

Dan

 

  

On Feb 7, 2010, at 6:55 AM, Matus Chochlik wrote:

> On Sun, Feb 7, 2010 at 12:52 PM, Matus Chochlik <chochlik_at_[hidden]> wrote:
>> On Sun, Feb 7, 2010 at 3:52 AM, Daniel Larimer <dlarimer_at_[hidden]> wrote:
>>> I have been playing with some code and recently developed a very efficient, extensible, and easy to use API for performing remote procedure calls (with multiple protocols). I am writing to gauge interest and get feedback on the user API. The native "protocol" is a custom combined tcp/udp protocol using multi-cast for discovery, but it would be very easy to add a shared memory solution, a dbus, XML/RPC, CORBA, etc back end to the user api.
>>>
>> [snip]
>>>
>>> META_INTERFACE( SomeClass,
>>> METHOD(add)
>>> METHOD(sub)
>>> METHOD(inout)
>>> )
>>>
>> Concerning this meta-interface declaration you might want to take a look at
>> the Mirror library, which can provide a lot of meta-data at both compile-time
>> and run-time.
>>
>> Both the C++98 and C++0x versions are in the Boost Vault and the C++0x
>> version can be also found on sourceforge:
>> http://sourceforge.net/projects/mirror-lib/
>>
>> the docs for the new version can be found here (though they are nowhere
>> near to finished, yet)
> here (sorry): http://kifri.fri.uniza.sk/~chochlik/mirror-lib/html/
>>
>> [snip]
>>
> BR
>
> matus
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk