feat update
All checks were successful
linux-aarch64-cpu-gcc / linux-gcc-aarch64 (push) Successful in 1m52s
linux-arm-gcc / linux-gcc-armhf (push) Successful in 2m6s
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m59s
linux-mips64-gcc / linux-gcc-mips64el (Debug) (push) Successful in 2m46s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 2m48s
linux-mips64-gcc / linux-gcc-mips64el (Release) (push) Successful in 2m51s

This commit is contained in:
tqcq 2024-04-16 20:02:53 +08:00
parent 569d08139d
commit 440536676d
3 changed files with 161 additions and 23 deletions

View File

@ -10,8 +10,9 @@
#include "sled/synchronization/event.h"
#include "sled/synchronization/mutex.h"
#include "sled/task_queue/task_queue_base.h"
#include "sled/variant.h"
#include "sled/utility/forward_on_copy.h"
#include <atomic>
#include <future>
#include <list>
namespace sled {
@ -48,7 +49,8 @@ struct FutureData {
~FutureData() { DecrementFuturesUsage(); }
std::atomic_int state{kNotCompletedFuture};
sled::variant<sled::monostate, T, FailureT> value;
// sled::variant<sled::monostate, T, FailureT> value;
sled::any value;
std::list<std::function<void(const T &)>> success_callbacks;
std::list<std::function<void(const FailureT &)>> failure_callbacks;
sled::Mutex mutex_;
@ -130,7 +132,8 @@ public:
if (!IsCompleted()) Wait();
if (IsSucceeded()) {
try {
return sled::get<T>(data_->value);
// return sled::get<T>(data_->value);
return sled::any_cast<T>(data_->value);
} catch (...) {}
}
return T();
@ -140,7 +143,8 @@ public:
{
SLED_ASSERT(data_ != nullptr, "Future is not valid");
if (!IsCompleted()) { Wait(); }
return sled::get<T>(data_->value);
// return sled::get<T>(data_->value);
return sled::any_cast<T>(data_->value);
}
FailureT FailureReason() const
@ -149,7 +153,8 @@ public:
if (!IsCompleted()) { Wait(); }
if (IsFailed()) {
try {
return sled::get<FailureT>(data_->value);
// return sled::get<FailureT>(data_->value);
return sled::any_cast<FailureT>(data_->value);
} catch (...) {}
}
return FailureT();
@ -176,7 +181,8 @@ public:
}
if (call_it) {
try {
f(sled::get<T>(data_->value));
// f(sled::get<T>(data_->value));
f(sled::any_cast<T>(data_->value));
} catch (...) {}
}
return Future<T, FailureT>(data_);
@ -203,7 +209,8 @@ public:
}
if (call_it) {
try {
f(sled::get<FailureT>(data_->value));
// f(sled::get<FailureT>(data_->value));
f(sled::any_cast<FailureT>(data_->value));
} catch (...) {}
}
return Future<T, FailureT>(data_);
@ -294,6 +301,20 @@ public:
return result;
}
template<typename Func, typename U = decltype(std::declval<eggs::invoke_result_t<Func, T>().Result()>)>
Future<U, FailureT> AndThen(Func &&f) const noexcept
{
return FlatMap([f](const T &) { return f(); });
}
template<typename T2, typename U = typename std::decay<T2>::type>
Future<U, FailureT> AndThenValue(T2 &&value) const noexcept
{
Future<U, FailureT> result = Future<U, FailureT>::Create();
auto forward_on_copy = sled::MakeForwardOnCopy(std::forward<T2>(value));
return Map([forward_on_copy](const T &) noexcept { return forward_on_copy.value(); });
}
Future<T, FailureT> Via(TaskQueueBase *task_queue) const noexcept
{
SLED_ASSERT(task_queue != nullptr, "TaskQueue is not valid");
@ -365,6 +386,7 @@ private:
if (IsCompleted()) { return; }
try {
// data_->value.template emplace<T>(std::move(value));
// data_->value.template emplace<T>(std::move(value));
data_->value = std::move(value);
} catch (...) {}
@ -376,7 +398,8 @@ private:
for (const auto &f : callbacks) {
try {
f(sled::get<T>(data_->value));
// f(sled::get<T>(data_->value));
f(sled::any_cast<T>(data_->value));
} catch (...) {}
}
}
@ -396,6 +419,7 @@ private:
if (IsCompleted()) { return; }
try {
// data_->value.template emplace<FailureT>(std::move(reason));
// data_->value = std::move(reason);
data_->value = std::move(reason);
} catch (...) {}
data_->state.store(detail::kFailedFuture, std::memory_order_release);
@ -406,7 +430,8 @@ private:
for (const auto &f : callbacks) {
try {
f(sled::get<FailureT>(data_->value));
// f(sled::get<FailureT>(data_->value));
f(sled::any_cast<FailureT>(data_->value));
} catch (...) {}
}
}

View File

@ -1,9 +1,11 @@
#include <sled/futures/future.h>
#include <sled/system/thread.h>
#include <type_traits>
TEST_SUITE("future")
{
TEST_CASE("base success")
{
sled::Promise<int, std::string> p;
auto f = p.GetFuture();
@ -12,6 +14,7 @@ TEST_SUITE("future")
CHECK(f.IsValid());
CHECK_EQ(f.Result(), 42);
}
TEST_CASE("base failed")
{
sled::Promise<int, std::string> p;
@ -23,31 +26,65 @@ TEST_SUITE("future")
CHECK(f.IsValid());
CHECK_EQ(f.FailureReason(), "error");
}
TEST_CASE("throw")
{
sled::Promise<int, std::string> p;
auto f = p.GetFuture().Map([](int x) {
throw std::runtime_error("test");
return x;
});
p.Success(42);
REQUIRE(f.IsCompleted());
REQUIRE(f.IsFailed());
CHECK_EQ(f.FailureReason(), "test");
}
TEST_CASE("base failed")
{
sled::Promise<int, std::string> p;
auto f = p.GetFuture();
p.Failure("error");
REQUIRE(p.IsFilled());
REQUIRE(f.IsCompleted());
CHECK(f.Wait(-1));
CHECK(f.IsValid());
CHECK_EQ(f.FailureReason(), "error");
}
TEST_CASE("thread success") {}
TEST_CASE("map")
TEST_CASE("Map")
{
sled::Promise<int, std::string> p;
auto f = p.GetFuture();
auto f2 = f.Map([](int i) { return i + 1; });
auto f2 = f.Map([](int i) { return i + 1; })
.Map([](int i) { return std::to_string(i) + "00"; })
.Map([](const std::string &str) {
std::stringstream ss(str);
int x;
ss >> x;
return x;
});
p.Success(42);
CHECK(f2.Wait(-1));
CHECK_EQ(f2.Result(), 43);
CHECK_EQ(f2.Result(), 4300);
}
TEST_CASE("FlatMap")
{
// sled::Promise<int, std::string> p;
// auto f = p.GetFuture().FlatMap([](int i) {
// auto str = std::to_string(i);
// sled::Promise<std::string, std::string> p;
// p.Success(str);
//
// return p.GetFuture();
// });
// p.Success(42);
// CHECK(f.Wait(-1));
// CHECK_EQ(f.Result(), "42");
sled::Promise<int, std::string> p;
auto f = p.GetFuture().FlatMap([](int i) {
auto str = std::to_string(i);
sled::Promise<std::string, std::string> p;
p.Success(str);
return p.GetFuture();
});
p.Success(42);
CHECK(f.IsCompleted());
CHECK_EQ(f.Result(), "42");
}
TEST_CASE("Via")

View File

@ -0,0 +1,76 @@
#ifndef SLED_UTILITY_FORWARD_ON_COPY_H
#define SLED_UTILITY_FORWARD_ON_COPY_H
#pragma once
#include "sled/any.h"
namespace sled {
namespace detail {
struct ForwardOnCopyTag {};
};// namespace detail
template<typename T>
struct ForwardOnCopy {
ForwardOnCopy(ForwardOnCopy &other)
: is_moved_(other.is_moved_),
value_(is_moved_ ? other.value_ : std::move(other.value_))
{}
// ForwardOnCopy(ForwardOnCopy &&other) noexcept;
ForwardOnCopy &operator=(ForwardOnCopy &other)
{
is_moved_ = other.is_moved_;
value_ = is_moved_ ? other.value_ : std::move(other.value_);
return *this;
}
// ForwardOnCopy &operator=(ForwardOnCopy &&other) noexcept;
T value() const
{
if (is_moved_) {
return std::move(sled::any_cast<T>(value_));
} else {
return sled::any_cast<T>(value_);
}
}
private:
bool is_moved_;
sled::any value_;
};
template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T value)
{
ForwardOnCopy<T> result;
result.is_moved_ = false;
result.value_ = value;
return result;
}
template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T &value)
{
ForwardOnCopy<T> result;
result.is_moved_ = false;
result.value_ = value;
return result;
}
template<typename T>
ForwardOnCopy<T>
MakeForwardOnCopy(T &&value)
{
ForwardOnCopy<T> result;
result.is_moved_ = true;
result.value_ = std::move(value);
return result;
}
}// namespace sled
#endif// SLED_UTILITY_FORWARD_ON_COPY_H