mirror of
https://github.com/Naios/continuable.git
synced 2026-10-28 18:07:24 +08:00
Implement make_cancelling_continuable()
* Can be used to cancel the chain when being inside a handler
This commit is contained in:
parent
4127c02c3f
commit
f469b7058a
@ -360,10 +360,11 @@ public:
|
|||||||
/// \since 2.0.0
|
/// \since 2.0.0
|
||||||
template <typename OData, typename OAnnotation>
|
template <typename OData, typename OAnnotation>
|
||||||
auto fail(continuable_base<OData, OAnnotation>&& continuation) && {
|
auto fail(continuable_base<OData, OAnnotation>&& continuation) && {
|
||||||
return std::move(*this).fail(
|
return std::move(*this) //
|
||||||
[continuation = std::move(continuation).freeze()](exception_t) mutable {
|
.fail([continuation = std::move(continuation).freeze()] //
|
||||||
std::move(continuation).done();
|
(exception_t) mutable {
|
||||||
});
|
std::move(continuation).done(); //
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A method which allows to use an overloaded callable for the error
|
/// A method which allows to use an overloaded callable for the error
|
||||||
@ -866,6 +867,35 @@ constexpr auto make_exceptional_continuable(Exception&& exception) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a continuable_base with the parameterized result which never
|
||||||
|
/// resolves its promise and thus cancels the asynchronous continuation chain.
|
||||||
|
///
|
||||||
|
/// This can be used to cancel an asynchronous continuation chain when
|
||||||
|
/// returning a continuable_base from a handler where other paths could
|
||||||
|
/// possibly continue the asynchronous chain. See an example below:
|
||||||
|
/// ```cpp
|
||||||
|
/// do_sth().then([weak = this->weak_from_this()]() -> continuable<> {
|
||||||
|
/// if (auto me = weak.lock()) {
|
||||||
|
/// return do_sth_more();
|
||||||
|
/// } else {
|
||||||
|
/// // Abort the asynchronous continuation chain since the
|
||||||
|
/// // weakly referenced object expired previously.
|
||||||
|
/// return make_cancelling_continuable<void>();
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// \tparam Signature The fake signature of the returned continuable.
|
||||||
|
///
|
||||||
|
/// \since 4.0.0
|
||||||
|
template <typename... Signature>
|
||||||
|
auto make_cancelling_continuable() {
|
||||||
|
static_assert(sizeof...(Signature) > 0,
|
||||||
|
"Requires at least one type for the fake signature!");
|
||||||
|
|
||||||
|
return make_continuable<Signature...>([](auto&&) { /* ... */ });
|
||||||
|
}
|
||||||
|
|
||||||
/// Can be used to recover to from a failure handler,
|
/// Can be used to recover to from a failure handler,
|
||||||
/// the result handler which comes after will be called with the
|
/// the result handler which comes after will be called with the
|
||||||
/// corresponding result.
|
/// corresponding result.
|
||||||
|
|||||||
@ -45,7 +45,8 @@ TYPED_TEST(single_dimension_tests, are_called_on_destruct) {
|
|||||||
ASSERT_ASYNC_TYPES(this->supply(tag1{}), tag1);
|
ASSERT_ASYNC_TYPES(this->supply(tag1{}), tag1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> auto create_incomplete(T* me) {
|
template <typename T>
|
||||||
|
auto create_incomplete(T* me) {
|
||||||
return me->make(identity<>{}, identity<void>{}, [](auto&& callback) mutable {
|
return me->make(identity<>{}, identity<void>{}, [](auto&& callback) mutable {
|
||||||
// Destruct the callback here
|
// Destruct the callback here
|
||||||
auto destroy = std::forward<decltype(callback)>(callback);
|
auto destroy = std::forward<decltype(callback)>(callback);
|
||||||
@ -53,7 +54,16 @@ template <typename T> auto create_incomplete(T* me) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> auto assert_invocation(T* me) {
|
template <typename T>
|
||||||
|
auto create_incomplete_cancelling(T* me) {
|
||||||
|
return me->make(identity<>{}, identity<void>{}, [](auto&& callback) mutable {
|
||||||
|
make_cancelling_continuable<void>().next(
|
||||||
|
std::forward<decltype(callback)>(callback));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto assert_invocation(T* me) {
|
||||||
return me->make(identity<>{}, identity<void>{},
|
return me->make(identity<>{}, identity<void>{},
|
||||||
[](auto&& /*callback*/) mutable { FAIL(); });
|
[](auto&& /*callback*/) mutable { FAIL(); });
|
||||||
}
|
}
|
||||||
@ -90,6 +100,18 @@ TYPED_TEST(single_dimension_tests, are_not_finished_when_not_continued) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TYPED_TEST(single_dimension_tests, are_not_finished_when_cancelling) {
|
||||||
|
{
|
||||||
|
auto chain = create_incomplete_cancelling(this);
|
||||||
|
ASSERT_ASYNC_INCOMPLETION(std::move(chain));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto chain = create_incomplete_cancelling(this);
|
||||||
|
ASSERT_ASYNC_INCOMPLETION(std::move(chain).then(this->supply()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TYPED_TEST(single_dimension_tests, freeze_is_kept_across_the_chain) {
|
TYPED_TEST(single_dimension_tests, freeze_is_kept_across_the_chain) {
|
||||||
{
|
{
|
||||||
auto chain = this->supply().freeze().then([=] { return this->supply(); });
|
auto chain = this->supply().freeze().then([=] { return this->supply(); });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user