$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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