add Future::Completer::RunAfter()
This commit is contained in:
parent
ff529a521a
commit
81f9bda412
@ -5,6 +5,7 @@
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
@ -258,7 +259,8 @@ class Future<T>::Completer final {
|
||||
}
|
||||
|
||||
public:
|
||||
Completer& Attach(const std::shared_ptr<void>& ptr) {
|
||||
template <typename V>
|
||||
Completer& Attach(const std::shared_ptr<V>& ptr) {
|
||||
internal_->Listen([ptr](auto&) {});
|
||||
return *this;
|
||||
}
|
||||
@ -300,6 +302,40 @@ class Future<T>::Completer final {
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename V, FutureLike Fu, typename... Args>
|
||||
static void RunAfter_Each(
|
||||
const std::shared_ptr<V>& ptr, Fu fu, Args&&... args) {
|
||||
fu.Attach(ptr);
|
||||
RunAfter_Each(ptr, std::forward<Args>(args)...);
|
||||
}
|
||||
static void RunAfter_Each(const std::shared_ptr<void>&) noexcept { }
|
||||
|
||||
public:
|
||||
template <typename F, typename... Args>
|
||||
Completer& RunAfter(F&& f, Args&&... args) {
|
||||
struct A final {
|
||||
public:
|
||||
using Tuple = std::tuple<std::remove_reference_t<Args>...>;
|
||||
|
||||
public:
|
||||
A(const Completer& self, F&& f, Tuple&& args) noexcept
|
||||
: self_(self), f_(std::move(f)), args_(std::move(args)) { }
|
||||
~A() noexcept {
|
||||
self_.Run([this]() { return std::apply(f_, args_); });
|
||||
}
|
||||
|
||||
private:
|
||||
Completer self_;
|
||||
F f_;
|
||||
Tuple args_;
|
||||
};
|
||||
RunAfter_Each(
|
||||
std::make_shared<A>(*this, std::move(f), std::make_tuple(args...)),
|
||||
std::forward<Args>(args)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
Future<T> future() const noexcept {
|
||||
assert(nullptr != internal_);
|
||||
|
@ -421,6 +421,45 @@ TEST(FutureCompleter, RunAsyncWithThrow) {
|
||||
[](auto&) -> int32_t { throw nf7::Exception {"helloworld"}; });
|
||||
}
|
||||
|
||||
TEST(FutureCompleter, RunAfterWithArgsImmediately) {
|
||||
nf7::Future<int32_t> fu1 {1};
|
||||
nf7::Future<int32_t> fu2 {2};
|
||||
nf7::Future<int32_t> fu3 {3};
|
||||
|
||||
auto fu = nf7::Future<int32_t>::Completer {}
|
||||
.RunAfter(
|
||||
[](auto& a, auto& b, auto& c) {
|
||||
return a.value()+b.value()+c.value();
|
||||
}, fu1, fu2, fu3)
|
||||
.future();
|
||||
ASSERT_TRUE(fu.done());
|
||||
EXPECT_EQ(fu.value(), int32_t {6});
|
||||
}
|
||||
TEST(FutureCompleter, RunAfterWithArgsLazy) {
|
||||
nf7::Future<int32_t> fu1 {1};
|
||||
nf7::Future<int32_t>::Completer comp2;
|
||||
nf7::Future<int32_t> fu3 {3};
|
||||
|
||||
auto fu = nf7::Future<int32_t>::Completer {}
|
||||
.RunAfter(
|
||||
[](auto& a, auto& b, auto& c) {
|
||||
return a.value()+b.value()+c.value();
|
||||
}, fu1, comp2.future(), fu3)
|
||||
.future();
|
||||
EXPECT_TRUE(fu.yet());
|
||||
|
||||
comp2.Complete(100);
|
||||
ASSERT_TRUE(fu.done());
|
||||
EXPECT_EQ(fu.value(), 104);
|
||||
}
|
||||
TEST(FutureCompleter, RunAfterWithoutTargets) {
|
||||
auto fu = nf7::Future<int32_t>::Completer {}
|
||||
.RunAfter([]() { return 666; })
|
||||
.future();
|
||||
ASSERT_TRUE(fu.done());
|
||||
EXPECT_EQ(fu.value(), int32_t {666});
|
||||
}
|
||||
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
TEST(Future, DeathByListenInCallback) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user