Boost logo

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