Recover continuable after invoking void fail handlers, s.t. continuable after void fail handlers invoked can be wait. Solve second case of issue #46.

This commit is contained in:
Yuan Yao 2022-05-19 22:01:49 +08:00
parent ed8310e345
commit 18e644045f
4 changed files with 35 additions and 19 deletions

View File

@ -293,16 +293,6 @@ constexpr void invoke_no_except(T&& callable, Args&&... args) noexcept {
std::forward<T>(callable)(std::forward<Args>(args)...); std::forward<T>(callable)(std::forward<Args>(args)...);
} }
template <typename... Args, typename T>
void invoke_void_no_except(identity<exception_arg_t, Args...>,
T&& /*callable*/) noexcept {
// Don't invoke the next failure handler when being in an exception handler
}
template <typename... Args, typename T>
void invoke_void_no_except(identity<Args...>, T&& callable) noexcept {
std::forward<T>(callable)();
}
template <typename T, typename... Args> template <typename T, typename... Args>
constexpr auto make_invoker(T&& invoke, identity<Args...>) { constexpr auto make_invoker(T&& invoke, identity<Args...>) {
return invoker<std::decay_t<T>, identity<Args...>>(std::forward<T>(invoke)); return invoker<std::decay_t<T>, identity<Args...>>(std::forward<T>(invoke));
@ -373,9 +363,8 @@ inline auto invoker_of(identity<void>) {
CONTINUABLE_BLOCK_TRY_BEGIN CONTINUABLE_BLOCK_TRY_BEGIN
invoke_callback(std::forward<decltype(callback)>(callback), invoke_callback(std::forward<decltype(callback)>(callback),
std::forward<decltype(args)>(args)...); std::forward<decltype(args)>(args)...);
invoke_void_no_except(
identity<traits::unrefcv_t<decltype(args)>...>{}, invoke_no_except(std::forward<decltype(next_callback)>(next_callback));
std::forward<decltype(next_callback)>(next_callback));
CONTINUABLE_BLOCK_TRY_END CONTINUABLE_BLOCK_TRY_END
}, },
identity<>{}); identity<>{});

View File

@ -194,3 +194,15 @@ TYPED_TEST(single_dimension_tests, token_remap_ignore) {
ASSERT_TRUE(value.is_value()); ASSERT_TRUE(value.is_value());
} }
TYPED_TEST(single_dimension_tests, wait_test_issue_46) {
bool handled = false;
make_exceptional_continuable<void>(supply_test_exception())
.fail([&]{
EXPECT_FALSE(handled);
handled = true;
})
.apply(cti::transforms::wait());
ASSERT_TRUE(handled);
}

View File

@ -39,7 +39,7 @@ TYPED_TEST(single_dimension_tests, are_yielding_error_result) {
get_test_exception_proto()); get_test_exception_proto());
} }
TYPED_TEST(single_dimension_tests, are_never_completed_after_error_handled) { TYPED_TEST(single_dimension_tests, are_completed_after_error_handled) {
auto handled = std::make_shared<bool>(false); auto handled = std::make_shared<bool>(false);
auto continuation = this->supply_exception(supply_test_exception()) auto continuation = this->supply_exception(supply_test_exception())
.fail([handled](cti::exception_t) { .fail([handled](cti::exception_t) {
@ -47,10 +47,23 @@ TYPED_TEST(single_dimension_tests, are_never_completed_after_error_handled) {
*handled = true; *handled = true;
}); });
ASSERT_ASYNC_INCOMPLETION(std::move(continuation)); ASSERT_ASYNC_COMPLETION(std::move(continuation));
ASSERT_TRUE(*handled); ASSERT_TRUE(*handled);
} }
TYPED_TEST(single_dimension_tests, are_recoverable_after_error_handled) {
auto recovered = std::make_shared<bool>(false);
auto continuation = this->supply_exception(supply_test_exception())
.fail([](cti::exception_t){})
.then([recovered]{
ASSERT_FALSE(*recovered);
*recovered = true;
});
ASSERT_ASYNC_COMPLETION(std::move(continuation));
ASSERT_TRUE(*recovered);
}
TYPED_TEST(single_dimension_tests, fail_is_accepting_plain_continuables) { TYPED_TEST(single_dimension_tests, fail_is_accepting_plain_continuables) {
auto handled = std::make_shared<bool>(false); auto handled = std::make_shared<bool>(false);
auto handler = this->supply().then([handled] { auto handler = this->supply().then([handled] {
@ -61,7 +74,7 @@ TYPED_TEST(single_dimension_tests, fail_is_accepting_plain_continuables) {
auto continuation = auto continuation =
this->supply_exception(supply_test_exception()).fail(std::move(handler)); this->supply_exception(supply_test_exception()).fail(std::move(handler));
ASSERT_ASYNC_INCOMPLETION(std::move(continuation)); ASSERT_ASYNC_COMPLETION(std::move(continuation));
ASSERT_TRUE(*handled); ASSERT_TRUE(*handled);
} }
@ -109,13 +122,13 @@ TYPED_TEST(single_dimension_tests, are_flow_error_accepting) {
*handled = true; *handled = true;
})); }));
ASSERT_ASYNC_INCOMPLETION(std::move(continuation)); ASSERT_ASYNC_COMPLETION(std::move(continuation));
ASSERT_TRUE(*handled); ASSERT_TRUE(*handled);
} }
TYPED_TEST(single_dimension_tests, are_exceptions_partial_applyable) { TYPED_TEST(single_dimension_tests, are_exceptions_partial_applyable) {
bool handled = false; bool handled = false;
ASSERT_ASYNC_INCOMPLETION( ASSERT_ASYNC_COMPLETION(
this->supply_exception(supply_test_exception()).fail([&]() -> void { this->supply_exception(supply_test_exception()).fail([&]() -> void {
EXPECT_FALSE(handled); EXPECT_FALSE(handled);
handled = true; handled = true;

View File

@ -170,10 +170,12 @@ TYPED_TEST(single_dimension_tests, multipath_exception_is_continuable) {
TYPED_TEST(single_dimension_tests, multipath_exception_is_autocanceled) { TYPED_TEST(single_dimension_tests, multipath_exception_is_autocanceled) {
bool caught = false; bool caught = false;
ASSERT_ASYNC_INCOMPLETION( ASSERT_ASYNC_COMPLETION(
this->supply_exception(supply_test_exception()).fail([&](exception_t) { this->supply_exception(supply_test_exception()).fail([&](exception_t) {
EXPECT_FALSE(caught); EXPECT_FALSE(caught);
caught = true; caught = true;
}).fail([](exception_t){
FAIL();
})); }));
ASSERT_TRUE(caught); ASSERT_TRUE(caught);
} }