Skip to content

Commit

Permalink
Propagate non-boost exceptions in concurrency code
Browse files Browse the repository at this point in the history
Use the existing dispatch::current_exception() workaround for
boost:future's incompatibility with std::exception_ptr in more places,
namely wrap any continuation call and exception handling code in
rethrowing code.

This is in addition to previous places, which were on the boost/pplx
boundary.
  • Loading branch information
vslavik committed Aug 1, 2023
1 parent 8b564aa commit 8034c28
Showing 1 changed file with 62 additions and 21 deletions.
83 changes: 62 additions & 21 deletions src/concurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ void set_current_exception(boost::promise<T>& pr)
template<typename T>
void set_current_exception(std::shared_ptr<boost::promise<T>> pr) { set_current_exception(*pr); }

#define RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT() catch ( ... ) { boost::rethrow_exception(dispatch::current_exception()); }


template<typename T, typename FutureType>
class future_base
Expand Down Expand Up @@ -365,7 +367,11 @@ class future : public future_base<T, future<T>>
typedef detail::continuation_calling_helper<typename detail::argument_type<typename std::decay<F>::type>::arg0_type> cch;
return this->f_.then(detail::background_queue_executor::get(),
[f{std::move(continuation)}](boost::future<T> x){
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
try
{
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});
}

Expand All @@ -375,7 +381,11 @@ class future : public future_base<T, future<T>>
typedef detail::continuation_calling_helper<typename detail::argument_type<typename std::decay<F>::type>::arg0_type> cch;
return this->f_.then(detail::main_thread_executor::get(),
[f{std::move(continuation)}](boost::future<T> x) {
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
try
{
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});
}

Expand All @@ -386,11 +396,15 @@ class future : public future_base<T, future<T>>
wxWeakRef<Window> weak(self);
return this->f_.then(detail::main_thread_executor::get(),
[weak, f{std::move(continuation)}](boost::future<T> x){
if (weak)
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
else
BOOST_THROW_EXCEPTION(detail::window_dismissed());
});
try
{
if (weak)
return detail::call_and_unwrap_if_future(f, cch::unpack_arg(std::move(x)));
else
BOOST_THROW_EXCEPTION(detail::window_dismissed());
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});
};

template<typename Window>
Expand Down Expand Up @@ -438,8 +452,12 @@ class future<void> : public future_base<void, future<void>>
typedef detail::continuation_calling_helper<typename detail::argument_type<typename std::decay<F>::type>::arg0_type> cch;
return this->f_.then(detail::background_queue_executor::get(),
[f{std::move(continuation)}](boost::future<void> x){
cch::touch_arg(x);
return detail::call_and_unwrap_if_future(f);
try
{
cch::touch_arg(x);
return detail::call_and_unwrap_if_future(f);
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});
}

Expand All @@ -449,8 +467,12 @@ class future<void> : public future_base<void, future<void>>
typedef detail::continuation_calling_helper<typename detail::argument_type<typename std::decay<F>::type>::arg0_type> cch;
return this->f_.then(detail::main_thread_executor::get(),
[f{std::move(continuation)}](boost::future<void> x){
cch::touch_arg(x);
detail::call_and_unwrap_if_future(f);
try
{
cch::touch_arg(x);
detail::call_and_unwrap_if_future(f);
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});

}
Expand All @@ -461,14 +483,17 @@ class future<void> : public future_base<void, future<void>>
wxWeakRef<Window> weak(self);
return this->f_.then(detail::main_thread_executor::get(),
[weak, f{std::move(continuation)}](boost::future<void> x){
if (weak)
try
{
cch::touch_arg(x);
detail::call_and_unwrap_if_future(f);
if (weak)
{
cch::touch_arg(x);
detail::call_and_unwrap_if_future(f);
}
else
BOOST_THROW_EXCEPTION(detail::window_dismissed());
}
else
BOOST_THROW_EXCEPTION(detail::window_dismissed());

RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
});
};

Expand Down Expand Up @@ -497,7 +522,11 @@ auto future_base<T, FutureType>::catch_ex(F&& continuation) -> future<void>
}
catch (Ex& ex)
{
f(ex);
try
{
f(ex);
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
}
});
}
Expand All @@ -517,7 +546,11 @@ auto future_base<T, FutureType>::catch_all(F&& continuation) -> future<void>
}
catch (...)
{
f(dispatch::current_exception());
try
{
f(dispatch::current_exception());
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
}
});
}
Expand Down Expand Up @@ -576,7 +609,11 @@ template<class F>
inline auto async(F&& f) -> future<typename detail::future_unwrapper<typename std::invoke_result<F>::type>::type>
{
return {boost::async(detail::background_queue_executor::get(), [f{std::forward<F>(f)}]() {
return detail::call_and_unwrap_if_future(f);
try
{
return detail::call_and_unwrap_if_future(f);
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
})};
}

Expand All @@ -586,7 +623,11 @@ template<class F>
inline auto on_main(F&& f) -> future<typename detail::future_unwrapper<typename std::invoke_result<F>::type>::type>
{
return {boost::async(detail::main_thread_executor::get(), [f{std::forward<F>(f)}]() {
return detail::call_and_unwrap_if_future(f);
try
{
return detail::call_and_unwrap_if_future(f);
}
RETHROW_WITH_BOOST_EXCEPTION_PTR_SUPPORT();
})};
}

Expand Down

0 comments on commit 8034c28

Please sign in to comment.