|
Boost : |
Subject: Re: [boost] [rpc] Introducing Boost.Reflect, Boost.CMT, and Boost.RPC
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2011-07-29 23:08:03
On Jul 29, 2011, at 7:39 PM, Jose wrote:
>> I would like to know if I am barking up the right tree here and if anyone
>> has any feedback. If someone has a real project they would like to see this
>> code incorporated into I would be more than willing to focus my development
>> effort toward those needs.
>
> The three libraries look really useful. The documentation is clear but
> a bit sparse.
>
There is so much to cover. I never got around to discussing how CMT does
priority scheduling or too much detail into how real multi-threading works.
> RPC lib:
> - Can you compare yours to other widely used libraries, e.g.Thrift
>
1) No code generation required (best for C++ to C++, but with a proper JSON interface can communicate with any language)
- eliminate extra build steps
- changing your code or structs in one spot applies every where.
- expose any existing code as an RPC service in a non-intrusive manner.
2) Asynchronous operations performed via futures
- Boost.CMT allows simple single-threaded programs to appear
multi-threaded.
- Benefits of async, with ease of use of synchronous code.
- No need to have a real OS thread per 'async operation' nor block an OS thread waiting on a result.
3) Clean syntax, minimal macro usage
4) Automatic stubs, complete with full type erasure provided by boost::reflect::any_ptr<>
- expose the same interface over JSON-RPC/TCP/UDP/HTTP, XML-RPC, protocol buffers, boost::serialization, etc
- your algorithms interface with boost::reflect::any_ptr<> and so do not care if they are dealing with
an RPC stub a local object, or a local actor running in a separate thread.
5) boost::signals over RPC
6) Asynchronous RPC call:
Assuming you are using the mirror delegate then everything looks synchronous, but can be made asynchronous using boost::cmt
boost::any_ptr<Interface> client_ptr;
boost::cmt::async<ReturnType>( boost::bind(client_ptr->method_name, arg1, arg2 ) ).wait( timeout );
I have not yet implemented it, but boost::cmt::actor_interface will adapt all of the methods on an interface to return a future<> instead
of the real return value.
Thus:
boost::any_ptr<Interface,boost::cmt::actor_interface> client_ptr;
future<ReturnType> r = client_ptr->method_name( arg1, arg2 );
And of course, future<ReturnType> automatically casts to ReturnType and blocks (yields) if necessary. Then I would have a
boost::actor_ptr<Interface> that could cast to and from a boost::any_ptr<Interface>.
I am torn about making boost::cmt depend upon boost::reflect vs introducing yet another library called boost::actor and then having
boost::rpc depend upon boost::actor.
> CMT lib:
> - Can you compare your library to the use of coroutines in the
> Boostcon 2011 example
> https://github.com/chriskohlhoff/awesome
Awesome appears to provide stackless coroutines whereas CMT uses Boost.Context to provide a real stack per fiber.
> - Could you provide a more real-life example, e.g. a proxy like in the
> above example ?
I use 'coroutines/fibers/futures' any time I need to perform an asynchronous operation and then it turns into a
"synchronous" operation where all 'in-flight' tasks are multi-plexed on one real thread. When I actually want
to do things in 'parallel' I use boost::cmt::async() and get the return value as a future. So I could enqueue 10 tasks, then
wait for 10 results. I often spawn a long-running task that exits with a signal/flag and I 'join' it by waiting on its future.
Other things I do is have one fiber 'wait' on a boost::signal for a value from another fiber.
Lastly, any time I need to do inter-thread communication, I get the 'cmt::thread' and schedule an async task. The result is that
all of my code is thread-safe and lock-free as long as the shared resource is only accessed from one thread with other threads delegating
queries to it. (Much like boost::asio::strand keeps things 'thread safe').
The only thing I need to be careful about is long-running tasks that do not yield. They can block all other tasks in a particular thread. With boost CMT it is easy enough to spawn these tasks off into a real thread. I try to avoid any blocking system calls as they stall not only the current fiber, but all other tasks assigned to that thread.
> - Can you provide an example that shows how to handle timeouts ?
cmt::future<ReturnType> f = boost::cmt::async<ReturnType>( Functor, priority );
try {
ReturnType r = f.wait( timeout_us);
} catch( const boost::cmt::future_wait_timeout& e ) {
.. handle timeout here....
}
> thanks
> jose
> _______________________________________________
> 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