feat add future
All checks were successful
linux-x64-gcc / linux-gcc (Release) (push) Successful in 1m35s
linux-x64-gcc / linux-gcc (Debug) (push) Successful in 57s

This commit is contained in:
tqcq 2024-03-23 19:00:52 +08:00
parent c0a2b73d0d
commit 190bbe15aa
4 changed files with 85 additions and 33 deletions

View File

@ -238,6 +238,7 @@ private:
// -----------------------------------------------------------------------------
namespace promise_hpp {
template<typename T>
class promise final {
public:
@ -261,6 +262,8 @@ public:
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
promise GetFuture() const { return promise(*this); }
//
// get
//
@ -283,6 +286,11 @@ public:
void Wait() const noexcept { state_->Wait(); }
inline promise_wait_status WaitFor(const sled::TimeDelta &timeout_duration) const
{
return state_->wait_for(std::chrono::microseconds(timeout_duration.us()));
}
template<typename Rep, typename Period>
promise_wait_status WaitFor(const std::chrono::duration<Rep, Period> &timeout_duration) const
{
@ -628,6 +636,9 @@ private:
std::vector<handler> handlers_;
};
};
template<typename T>
using future = promise<T>;
}// namespace promise_hpp
// -----------------------------------------------------------------------------
@ -660,16 +671,18 @@ public:
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
promise GetFuture() const { return promise(*this); }
//
// get
//
void get() const { state_->get(); }
void Get() const { state_->get(); }
void get_or_default() const
void GetOr() const
{
try {
return get();
return Get();
} catch (...) {
// nothing
}
@ -679,16 +692,21 @@ public:
// wait
//
void wait() const noexcept { state_->wait(); }
void Wait() const noexcept { state_->wait(); }
inline promise_wait_status WaitFor(const sled::TimeDelta &timeout_duration) const
{
return state_->wait_for(timeout_duration);
}
template<typename Rep, typename Period>
promise_wait_status wait_for(const std::chrono::duration<Rep, Period> &timeout_duration) const
promise_wait_status WaitFor(const std::chrono::duration<Rep, Period> &timeout_duration) const
{
return state_->wait_for(timeout_duration);
}
template<typename Clock, typename Duration>
promise_wait_status wait_until(const std::chrono::time_point<Clock, Duration> &timeout_time) const
promise_wait_status WaitUntil(const std::chrono::time_point<Clock, Duration> &timeout_time) const
{
return state_->wait_until(timeout_time);
}
@ -697,12 +715,12 @@ public:
// resolve/reject
//
bool resolve() { return state_->resolve(); }
bool Resolve() { return state_->resolve(); }
bool reject(std::exception_ptr e) noexcept { return state_->reject(e); }
bool Reject(std::exception_ptr e) noexcept { return state_->reject(e); }
template<typename E>
bool reject(E &&e)
bool Reject(E &&e)
{
return state_->reject(std::make_exception_ptr(std::forward<E>(e)));
}
@ -712,11 +730,11 @@ public:
//
template<typename ResolveF, typename ResolveR = eggs::invoke_result_t<ResolveF>>
std::enable_if_t<is_promise_v<ResolveR>, promise<typename ResolveR::value_type>> then(ResolveF &&on_resolve)
std::enable_if_t<is_promise_v<ResolveR>, promise<typename ResolveR::value_type>> Then(ResolveF &&on_resolve)
{
promise<typename ResolveR::value_type> next;
then([n = next, f = std::forward<ResolveF>(on_resolve)]() mutable {
Then([n = next, f = std::forward<ResolveF>(on_resolve)]() mutable {
auto np = eggs::invoke(std::forward<decltype(f)>(f));
std::move(np)
.then([n](auto &&...nvs) mutable { n.resolve(std::forward<decltype(nvs)>(nvs)...); })
@ -727,36 +745,36 @@ public:
}
template<typename ResolveF>
auto then_all(ResolveF &&on_resolve)
auto ThenAll(ResolveF &&on_resolve)
{
return then([f = std::forward<ResolveF>(on_resolve)]() mutable {
return Then([f = std::forward<ResolveF>(on_resolve)]() mutable {
auto r = eggs::invoke(std::forward<decltype(f)>(f));
return make_all_promise(std::move(r));
});
}
template<typename ResolveF>
auto then_any(ResolveF &&on_resolve)
auto ThenAny(ResolveF &&on_resolve)
{
return then([f = std::forward<ResolveF>(on_resolve)]() mutable {
return Then([f = std::forward<ResolveF>(on_resolve)]() mutable {
auto r = eggs::invoke(std::forward<decltype(f)>(f));
return make_any_promise(std::move(r));
});
}
template<typename ResolveF>
auto then_race(ResolveF &&on_resolve)
auto ThenRace(ResolveF &&on_resolve)
{
return then([f = std::forward<ResolveF>(on_resolve)]() mutable {
return Then([f = std::forward<ResolveF>(on_resolve)]() mutable {
auto r = eggs::invoke(std::forward<decltype(f)>(f));
return make_race_promise(std::move(r));
});
}
template<typename ResolveF>
auto then_tuple(ResolveF &&on_resolve)
auto ThenTuple(ResolveF &&on_resolve)
{
return then([f = std::forward<ResolveF>(on_resolve)]() mutable {
return Then([f = std::forward<ResolveF>(on_resolve)]() mutable {
auto r = eggs::invoke(std::forward<decltype(f)>(f));
return make_tuple_promise(std::move(r));
});
@ -767,7 +785,7 @@ public:
//
template<typename ResolveF, typename ResolveR = eggs::invoke_result_t<ResolveF>>
std::enable_if_t<!is_promise_v<ResolveR>, promise<ResolveR>> then(ResolveF &&on_resolve)
std::enable_if_t<!is_promise_v<ResolveR>, promise<ResolveR>> Then(ResolveF &&on_resolve)
{
promise<ResolveR> next;
@ -779,7 +797,7 @@ public:
}
template<typename ResolveF, typename RejectF, typename ResolveR = eggs::invoke_result_t<ResolveF>>
std::enable_if_t<!is_promise_v<ResolveR>, promise<ResolveR>> then(ResolveF &&on_resolve, RejectF &&on_reject)
std::enable_if_t<!is_promise_v<ResolveR>, promise<ResolveR>> Then(ResolveF &&on_resolve, RejectF &&on_reject)
{
promise<ResolveR> next;
@ -793,9 +811,9 @@ public:
//
template<typename RejectF>
promise<void> except(RejectF &&on_reject)
promise<void> Except(RejectF &&on_reject)
{
return then([]() {}, std::forward<RejectF>(on_reject));
return Then([]() {}, std::forward<RejectF>(on_reject));
}
//
@ -803,9 +821,9 @@ public:
//
template<typename FinallyF>
promise<void> finally(FinallyF &&on_finally)
promise<void> Finally(FinallyF &&on_finally)
{
return then([f = on_finally]() { eggs::invoke(std::move(f)); },
return Then([f = on_finally]() { eggs::invoke(std::move(f)); },
[f = on_finally](std::exception_ptr e) {
eggs::invoke(std::move(f));
std::rethrow_exception(e);
@ -839,6 +857,16 @@ private:
cond_var_.Wait(lock, [this]() { return status_ != status::pending; });
}
promise_wait_status wait_for(const sled::TimeDelta &timeout_duration) const
{
sled::MutexLock lock(&mutex_);
// std::unique_lock lock(mutex_);
// return cond_var_.wait_for(lock, timeout_duration, [this]() { return status_ != status::pending; })
return cond_var_.WaitFor(lock, timeout_duration, [this]() { return status_ != status::pending; })
? promise_wait_status::no_timeout
: promise_wait_status::timeout;
}
template<typename Rep, typename Period>
promise_wait_status wait_for(const std::chrono::duration<Rep, Period> &timeout_duration) const
{
@ -856,7 +884,8 @@ private:
sled::MutexLock lock(&mutex_);
// std::unique_lock lock(mutex_);
// return cond_var_.wait_until(lock, timeout_time, [this]() { return status_ != status::pending; })
return cond_var_.WaitFor(lock, timeout_time, [this]() { return status_ != status::pending; })
auto duration = timeout_time - std::chrono::system_clock::now();
return cond_var_.WaitFor(lock, duration, [this]() { return status_ != status::pending; })
? promise_wait_status::no_timeout
: promise_wait_status::timeout;
}
@ -1048,7 +1077,7 @@ inline promise<void>
make_resolved_promise()
{
promise<void> result;
result.resolve();
result.Resolve();
return result;
}
@ -1070,7 +1099,7 @@ promise<void>
make_rejected_promise(E &&e)
{
promise<void> result;
result.reject(std::forward<E>(e));
result.Reject(std::forward<E>(e));
return result;
}
@ -1314,6 +1343,9 @@ struct IsPromiseRet : promise_hpp::is_promise_r<TRet, TPromise> {};
template<typename T>
using Promise = promise_hpp::promise<T>;
template<typename T>
using Future = promise_hpp::future<T>;
template<typename T>
inline auto
MakePromise() -> Promise<T>
@ -1332,7 +1364,7 @@ inline auto
MakeResolvedPromise() -> Promise<void>
{
Promise<void> result;
result.resolve();
result.Resolve();
return result;
}
@ -1348,7 +1380,7 @@ inline Promise<void>
make_rejected_promise(E &&e)
{
Promise<void> result;
result.reject(std::forward<E>(e));
result.Reject(std::forward<E>(e));
return result;
}

View File

@ -10,6 +10,9 @@
#include "sled/filesystem/path.h"
#include "sled/filesystem/temporary_file.h"
// futures
#include "sled/futures/promise.h"
// lang
#include "lang/attributes.h"

View File

@ -9,6 +9,7 @@
#define SLED_UNITS_TIME_DELTA_H
#include "sled/units/unit_base.h"
#include <chrono>
#include <string>
namespace sled {
@ -43,10 +44,10 @@ public:
return FromValue(value);
}
template<typename T, typename V>
inline TimeDelta(std::chrono::duration<T, V> duration)
template<typename Clock, typename Duration>
inline TimeDelta(const std::chrono::duration<Clock, Duration> &duration)
{
*this = Micros(std::chrono::duration_cast<std::chrono::microseconds>(duration));
*this = FromValue(std::chrono::duration_cast<std::chrono::microseconds>(duration).count());
}
TimeDelta() = delete;

View File

@ -19,3 +19,19 @@ TEST(Promise, Basic)
});
p.Resolve(1);
}
TEST(Future, Basic)
{
auto p = sled::Promise<int>();
auto future = p.GetFuture()
.Then([](int v) {
EXPECT_EQ(v, 1);
return v + 10;
})
.Then([](int v) {
EXPECT_EQ(v, 11);
return v + 10;
});
p.Resolve(1);
EXPECT_EQ(future.Get(), 21);
}