|
Boost : |
Subject: Re: [boost] Interest in Remote Procedure Call Library?
From: Matus Chochlik (chochlik_at_[hidden])
Date: 2010-02-08 05:55:12
On Sun, Feb 7, 2010 at 5:30 PM, Daniel Larimer <dlarimer_at_[hidden]> wrote:
> 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.
Sigh, the docs still leave a lot to be desired, but I'm working on it so
it hopefully gets better soon.
Anyway, there is a run-time layer nicknamed "Lagoon" which provides
a dynamic interface based on the compile-time meta-data registered
with Mirror, that allows you to iterate through the member variables/
base classes/constructors/*member functions*/various specifiers/etc.
the docs can be found here: http://tinyurl.com/yz6pdbv
there is a template function called reflected_class<Class>()
(docs: http://tinyurl.com/ylag2tq) that returns a polymorphic
interface (meta_class: http://tinyurl.com/ylepo6e) reflecting a Class.
*Currently* it lacks the ability to call a function dynamically, but there is
a compile-time facility which can invoke a constructor or basically any
(member) function with a custom parameter supplier, through a uniform
interface and allows to pass the parameters for the function call from
any external source, a GUI, a database, an XML file, etc.
Similar thing will be added to the run-time layer, once some minor
issues are resolved. This way it will be possible to use a polymorphic
interface to create instances or to call a member function and
to supply the arguments in an application defined way.
But, what I was suggesting is that you could use the compile-time
meta-data provided by Mirror to generate the meta-data you are currently
registering with the META_INTERFACE and METHOD macros
(I did not look at the definition of these macros but there is a good chance
that this is possible)
There is a set of meta-function templates which work with the
meta_class returned by BOOST_MIRRORED_CLASS(Class),
for example:
member_variables<MetaClass> (http://tinyurl.com/yfygtay),
member_functions<MetaClass> (http://tinyurl.com/yggfqhe),
base_classes<MetaClass> (http://tinyurl.com/ylyvzkd),
etc.
which return ranges of meta-objects describing the members,
base classes, etc.
by using the compile-time meta-programming utilities
(http://tinyurl.com/ygv2ash) you can traverse or transform
these ranges into (nearly ;-)) whatever form you need.
>
> 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
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
-- ________________ ::matus_chochlik
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk