|
Boost : |
From: vicente.botet (vicente.botet_at_[hidden])
Date: 2008-04-14 07:21:44
Hi Olivier,
This is very elegant on the context of the future library.
I was thinking on some kind of mpl generation for the exception_ptr library
but I didn't thounk to wrappe the call.
----- Original Message -----
From: "Kowalke Oliver (QD IT PA AS)" <Oliver.Kowalke_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Monday, April 14, 2008 9:26 AM
Subject: Re: [boost] Review Request: future library (Gaskill version)
> Sorry - didn't read your docu carefully. As you say in the docs 'However,
> arbitrary user-defined exception types cannot be supported.'.
>
> What about to specify an mpl::vector with arbitrary user-defined exception
> types?
> I'm using your future library siunce last year with this little
> modification (at least for me it works).
> Oliver
>
> template<
> typename R,
> typename V = mpl::vector<>
> >
> class future_wrapper
> {
> public:
> future_wrapper(const boost::function<R (void)> &fn, const promise<R>
> &ft ) : fn_(fn), ft_(ft) {}; // stores fn and ft
> void operator()() throw() { // executes fn() and places the outcome
> into ft
>
> typedef typename boost::mpl::fold<
> V,
> detail::exec_function,
> detail::catch_exception< boost::mpl::_1, boost::mpl::_2 >
> >::type exec_type;
>
> detail::catch_ellipsis< exec_type >::exec( fn_, ft_);
> }
> private:
> boost::function<R (void)> fn_;
> promise<R> ft_;
> };
>
>
> struct exec_function
> {
> template< typename R >
> static void exec(
> boost::function< R ( void) > const& fn,
> boost::promise< R > & ft)
> { ft.set( fn() ); }
>
> static void exec(
> boost::function< void ( void) > const& fn,
> boost::promise< void > & ft)
> {
> fn();
> ft.set();
> }
> };
>
> template<
> typename P,
> typename E
> >
> struct catch_exception
> {
> template< typename R >
> static void exec(
> boost::function< R ( void) > const& fn,
> boost::promise< R > & ft)
> {
> try
> { P::exec( fn, ft); }
> catch ( E const& e)
> { ft.set_exception( e); }
> }
>
> static void exec(
> boost::function< void ( void) > const& fn,
> boost::promise< void > & ft)
> {
> try
> { P::exec( fn, ft); }
> catch ( E const& e)
> { ft.set_exception( e); }
> }
> };
>
> template< typename P >
> struct catch_ellipsis
> {
> template< typename R >
> static void exec(
> boost::function< R ( void) > const& fn,
> boost::promise< R > & ft)
> {
> try
> { P::exec( fn, ft); }
> catch (...)
> { ft.set_exception(boost::detail::current_exception() ); }
> }
>
> static void exec(
> boost::function< void ( void) > const& fn,
> boost::promise< void > & ft)
> {
> try
> { P::exec( fn, ft); }
> catch (...)
> { ft.set_exception(boost::detail::current_exception() ); }
> }
> };
>
>> Hello,
>> is it correct that user defined exceptions thrown by the
>> defered function object will be rethrown as as
>> std::runtime_error (if it was derived from std::exception) or
>> std::bad_exception?
>> If yes - what about specifying an mpl::vector with user
>> defined exception types (passing to future_wrapper etc.)?
>> regards, oliver
I see only a problem: the interface of the future_wrapper is changed.
Maybe something like
template<
typename R,
typename V = BOOST_EXCEPTION_PTR_USER_EXCEPTION_VECTOR
class future_wrapper ...
allow to preserv the interface.
Another problem is that we need to do the same for each class using the
exception_ptr library.
It will be nice if the exec_function, the catch_exception and the
catch_ellipsis do not depend directly on the promise<R>. I don't know if it
is possible to make a wrap_call template with a template parameter Promise
and having these three classes nested.
template <class template<class> PromiseTmpl>
struct wrap_call {
struct exec_function
{
template< typename R, class Policy= promise_policy< PromiseTmpl< R >
> >
static void exec(
boost::function< R ( void) > const& fn,
PromiseTmpl< R > & ft)
{ Policy::set(ft, fn() ); }
// ...
template <
typename V = BOOST_EXCEPTION_PTR_USER_EXCEPTION_VECTOR
>
struct call {
typedef typename boost::mpl::fold<
V,
wrap_call<PromiseTmpl>::exec_function,
wrap_call<PromiseTmpl>::catch_exception< boost::mpl::_1,
boost::mpl::_2 >
>::type exec_type;
typedef wrap_call<PromiseTmpl>::catch_ellipsis< exec_type > type;
};
}
A policy class should be needed to take care of the promise concept
interface
template <class Promise>
struct promise_policy {
void set(Promise& p, const R &v) {p.set(v);}
void set_exception(Promise& p, const exception_ptr&e)
{p.set_exception(e);}
};
And use it as follows
template<
typename R,
typename V = BOOST_EXCEPTION_PTR_USER_EXCEPTION_VECTOR
class future_wrapper {
// ...
future_wrapper(const boost::function<R (void)> &fn, const
promise<R> &ft ) : fn_(fn), ft_(ft) {}; // stores fn and ft
void operator()() throw() { // executes fn() and places the outcome
into ft
exception_ptr::wrap_call<promise>::call<V>::exec( fn_, ft_);
}
// ...
Do you think that this could work?
Best
_____________________
Vicente Juan Botet Escriba
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk