Make the wait transform throw a wait_transform_canceled_exception on cancellation

This commit is contained in:
Denis Blank 2020-04-09 16:03:47 +02:00
parent 5f84de0e86
commit d80f5ef3ec
3 changed files with 37 additions and 1 deletions

View File

@ -50,6 +50,18 @@
namespace cti { namespace cti {
namespace detail { namespace detail {
namespace transforms { namespace transforms {
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
class wait_transform_canceled_exception : public std::exception {
public:
wait_transform_canceled_exception() noexcept = default;
char const* what() const noexcept override {
return "cti::transforms::wait canceled due to cancellation of the "
"continuation";
}
};
#endif // CONTINUABLE_HAS_EXCEPTIONS
template <typename Hint> template <typename Hint>
struct sync_trait; struct sync_trait;
template <typename... Args> template <typename... Args>
@ -105,7 +117,11 @@ auto wait_and_unpack(continuable_base<Data, Annotation>&& continuable) {
return std::move(sync_result).get_value(); return std::move(sync_result).get_value();
} else { } else {
assert(sync_result.is_exception()); assert(sync_result.is_exception());
std::rethrow_exception(sync_result.get_exception()); if (exception_t e = sync_result.get_exception()) {
std::rethrow_exception(e);
} else {
throw wait_transform_canceled_exception();
}
} }
#else #else
return sync_result; return sync_result;

View File

@ -34,6 +34,7 @@
#include <chrono> #include <chrono>
#include <condition_variable> #include <condition_variable>
#include <utility> #include <utility>
#include <continuable/detail/features.hpp>
#include <continuable/detail/transforms/wait.hpp> #include <continuable/detail/transforms/wait.hpp>
namespace cti { namespace cti {
@ -41,6 +42,15 @@ namespace cti {
/// \{ /// \{
namespace transforms { namespace transforms {
#if defined(CONTINUABLE_HAS_EXCEPTIONS)
/// Is thrown from wait if the awaited continuable_base was cancelled,
/// which was signaled through resolving with a default
/// constructed exception type.
///
/// \since 4.1.0
using wait_transform_canceled_exception = detail::transforms::wait_transform_canceled_exception;
#endif // CONTINUABLE_HAS_EXCEPTIONS
/// Returns a transform that if applied to a continuable, /// Returns a transform that if applied to a continuable,
/// it will start the continuation chain and returns the result synchronously. /// it will start the continuation chain and returns the result synchronously.
/// The current thread is blocked until the continuation chain is finished. /// The current thread is blocked until the continuation chain is finished.
@ -53,6 +63,10 @@ namespace transforms {
/// | `continuable_base with <Arg>` | `Arg` | /// | `continuable_base with <Arg>` | `Arg` |
/// | `continuable_base with <Args...>` | `std::tuple<Args...>` | /// | `continuable_base with <Args...>` | `std::tuple<Args...>` |
/// ///
/// \throws wait_transform_canceled_exception if the awaited continuable_base
/// is cancelled, and thus was resolved with a default
/// constructed exception type.
///
/// \attention If exceptions are used, exceptions that are thrown, are rethrown /// \attention If exceptions are used, exceptions that are thrown, are rethrown
/// synchronously. /// synchronously.
/// ///

View File

@ -111,6 +111,12 @@ TYPED_TEST(single_dimension_tests, wait_test_exception) {
.apply(cti::transforms::wait()), .apply(cti::transforms::wait()),
test_exception); test_exception);
} }
TYPED_TEST(single_dimension_tests, wait_test_cancellation) {
ASSERT_THROW(make_cancelling_continuable<void>().apply(
cti::transforms::wait()),
transforms::wait_transform_canceled_exception);
}
#endif // CONTINUABLE_HAS_EXCEPTIONS #endif // CONTINUABLE_HAS_EXCEPTIONS
TYPED_TEST(single_dimension_tests, wait_for_test_sync) { TYPED_TEST(single_dimension_tests, wait_for_test_sync) {