Date: Tue, 7 Nov 2023 11:52:08 +0000
On Tue, Nov 7, 2023 at 11:40 AM Frederick Virchanza Gotham wrote:
>
> Actually I might need to add a constraint here to ensure that
> "set_value" won't throw an exception. The return type will need to
> have a move/copy constructor declared as 'noexcept'.
Here it is with template constraints to make sure that the return type
is both nothrow_copy_constructible and othrow_move_constructible.
Not sure whether lambda_default_retval should be a parameter taken by
value, or taken by R-value reference.
#include <functional> // function
#include <future> // async, future, launch, promise
#include <utility> // move, forward
#include <type_traits> // decay, invoke_result,
is_nothrow_copy_constructible, is_nothrow_move_constructible
template<typename FunctorType, typename... Params>
[[nodiscard]]
std::future< std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > >
async_noexcept(
std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > default_retval,
std::launch policy,
FunctorType &&f,
Params&&... args) noexcept
requires std::is_nothrow_copy_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
&& std::is_nothrow_move_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
{
typedef std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > R;
// The lambda on the next line is created on the stack, however
// there are no captures, so it's OK to invoke the lambda after
// it has gone out of scope (i.e. from another thread).
auto const mylambda = [](R lambda_default_retval, FunctorType
&&lambda_f, std::decay_t<Params>... lambda_args) -> R
{
try
{
return std::forward<FunctorType>(lambda_f)( lambda_args... );
}
catch(...)
{
return lambda_default_retval;
}
};
try
{
return std::async(
static_cast<std::launch>(policy),
mylambda,
default_retval,
std::forward<FunctorType>(f),
std::forward<Params>(args)... );
}
catch(...)
{
std::promise<R> mypromise;
std::future<R> myfuture = mypromise.get_future();
mypromise.set_value(default_retval); // This won't throw (see
constraints above)
return myfuture;
}
}
>
> Actually I might need to add a constraint here to ensure that
> "set_value" won't throw an exception. The return type will need to
> have a move/copy constructor declared as 'noexcept'.
Here it is with template constraints to make sure that the return type
is both nothrow_copy_constructible and othrow_move_constructible.
Not sure whether lambda_default_retval should be a parameter taken by
value, or taken by R-value reference.
#include <functional> // function
#include <future> // async, future, launch, promise
#include <utility> // move, forward
#include <type_traits> // decay, invoke_result,
is_nothrow_copy_constructible, is_nothrow_move_constructible
template<typename FunctorType, typename... Params>
[[nodiscard]]
std::future< std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > >
async_noexcept(
std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > default_retval,
std::launch policy,
FunctorType &&f,
Params&&... args) noexcept
requires std::is_nothrow_copy_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
&& std::is_nothrow_move_constructible_v< std::invoke_result_t<
std::decay_t<FunctorType>, std::decay_t<Params>... > >
{
typedef std::invoke_result_t< std::decay_t<FunctorType>,
std::decay_t<Params>... > R;
// The lambda on the next line is created on the stack, however
// there are no captures, so it's OK to invoke the lambda after
// it has gone out of scope (i.e. from another thread).
auto const mylambda = [](R lambda_default_retval, FunctorType
&&lambda_f, std::decay_t<Params>... lambda_args) -> R
{
try
{
return std::forward<FunctorType>(lambda_f)( lambda_args... );
}
catch(...)
{
return lambda_default_retval;
}
};
try
{
return std::async(
static_cast<std::launch>(policy),
mylambda,
default_retval,
std::forward<FunctorType>(f),
std::forward<Params>(args)... );
}
catch(...)
{
std::promise<R> mypromise;
std::future<R> myfuture = mypromise.get_future();
mypromise.set_value(default_retval); // This won't throw (see
constraints above)
return myfuture;
}
}
Received on 2023-11-07 11:52:20