add Future::Completer::RunAfter()
This commit is contained in:
parent
ff529a521a
commit
81f9bda412
@ -5,6 +5,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -258,7 +259,8 @@ class Future<T>::Completer final {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Completer& Attach(const std::shared_ptr<void>& ptr) {
|
template <typename V>
|
||||||
|
Completer& Attach(const std::shared_ptr<V>& ptr) {
|
||||||
internal_->Listen([ptr](auto&) {});
|
internal_->Listen([ptr](auto&) {});
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -300,6 +302,40 @@ class Future<T>::Completer final {
|
|||||||
return *this;
|
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:
|
public:
|
||||||
Future<T> future() const noexcept {
|
Future<T> future() const noexcept {
|
||||||
assert(nullptr != internal_);
|
assert(nullptr != internal_);
|
||||||
|
@ -421,6 +421,45 @@ TEST(FutureCompleter, RunAsyncWithThrow) {
|
|||||||
[](auto&) -> int32_t { throw nf7::Exception {"helloworld"}; });
|
[](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)
|
#if !defined(NDEBUG)
|
||||||
TEST(Future, DeathByListenInCallback) {
|
TEST(Future, DeathByListenInCallback) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user