From 190bbe15aa94b14d18e7e3f7b16a41aa0941d1bb Mon Sep 17 00:00:00 2001 From: tqcq <99722391+tqcq@users.noreply.github.com> Date: Sat, 23 Mar 2024 19:00:52 +0800 Subject: [PATCH] feat add future --- include/sled/futures/promise.h | 92 ++++++++++++++++++++++----------- include/sled/sled.h | 3 ++ include/sled/units/time_delta.h | 7 +-- src/futures/promise_test.cc | 16 ++++++ 4 files changed, 85 insertions(+), 33 deletions(-) diff --git a/include/sled/futures/promise.h b/include/sled/futures/promise.h index 7f40c35..b41944d 100644 --- a/include/sled/futures/promise.h +++ b/include/sled/futures/promise.h @@ -238,6 +238,7 @@ private: // ----------------------------------------------------------------------------- namespace promise_hpp { + template 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 promise_wait_status WaitFor(const std::chrono::duration &timeout_duration) const { @@ -628,6 +636,9 @@ private: std::vector handlers_; }; }; + +template +using future = promise; }// 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 - promise_wait_status wait_for(const std::chrono::duration &timeout_duration) const + promise_wait_status WaitFor(const std::chrono::duration &timeout_duration) const { return state_->wait_for(timeout_duration); } template - promise_wait_status wait_until(const std::chrono::time_point &timeout_time) const + promise_wait_status WaitUntil(const std::chrono::time_point &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 - bool reject(E &&e) + bool Reject(E &&e) { return state_->reject(std::make_exception_ptr(std::forward(e))); } @@ -712,11 +730,11 @@ public: // template> - std::enable_if_t, promise> then(ResolveF &&on_resolve) + std::enable_if_t, promise> Then(ResolveF &&on_resolve) { promise next; - then([n = next, f = std::forward(on_resolve)]() mutable { + Then([n = next, f = std::forward(on_resolve)]() mutable { auto np = eggs::invoke(std::forward(f)); std::move(np) .then([n](auto &&...nvs) mutable { n.resolve(std::forward(nvs)...); }) @@ -727,36 +745,36 @@ public: } template - auto then_all(ResolveF &&on_resolve) + auto ThenAll(ResolveF &&on_resolve) { - return then([f = std::forward(on_resolve)]() mutable { + return Then([f = std::forward(on_resolve)]() mutable { auto r = eggs::invoke(std::forward(f)); return make_all_promise(std::move(r)); }); } template - auto then_any(ResolveF &&on_resolve) + auto ThenAny(ResolveF &&on_resolve) { - return then([f = std::forward(on_resolve)]() mutable { + return Then([f = std::forward(on_resolve)]() mutable { auto r = eggs::invoke(std::forward(f)); return make_any_promise(std::move(r)); }); } template - auto then_race(ResolveF &&on_resolve) + auto ThenRace(ResolveF &&on_resolve) { - return then([f = std::forward(on_resolve)]() mutable { + return Then([f = std::forward(on_resolve)]() mutable { auto r = eggs::invoke(std::forward(f)); return make_race_promise(std::move(r)); }); } template - auto then_tuple(ResolveF &&on_resolve) + auto ThenTuple(ResolveF &&on_resolve) { - return then([f = std::forward(on_resolve)]() mutable { + return Then([f = std::forward(on_resolve)]() mutable { auto r = eggs::invoke(std::forward(f)); return make_tuple_promise(std::move(r)); }); @@ -767,7 +785,7 @@ public: // template> - std::enable_if_t, promise> then(ResolveF &&on_resolve) + std::enable_if_t, promise> Then(ResolveF &&on_resolve) { promise next; @@ -779,7 +797,7 @@ public: } template> - std::enable_if_t, promise> then(ResolveF &&on_resolve, RejectF &&on_reject) + std::enable_if_t, promise> Then(ResolveF &&on_resolve, RejectF &&on_reject) { promise next; @@ -793,9 +811,9 @@ public: // template - promise except(RejectF &&on_reject) + promise Except(RejectF &&on_reject) { - return then([]() {}, std::forward(on_reject)); + return Then([]() {}, std::forward(on_reject)); } // @@ -803,9 +821,9 @@ public: // template - promise finally(FinallyF &&on_finally) + promise 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 promise_wait_status wait_for(const std::chrono::duration &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 make_resolved_promise() { promise result; - result.resolve(); + result.Resolve(); return result; } @@ -1070,7 +1099,7 @@ promise make_rejected_promise(E &&e) { promise result; - result.reject(std::forward(e)); + result.Reject(std::forward(e)); return result; } @@ -1314,6 +1343,9 @@ struct IsPromiseRet : promise_hpp::is_promise_r {}; template using Promise = promise_hpp::promise; +template +using Future = promise_hpp::future; + template inline auto MakePromise() -> Promise @@ -1332,7 +1364,7 @@ inline auto MakeResolvedPromise() -> Promise { Promise result; - result.resolve(); + result.Resolve(); return result; } @@ -1348,7 +1380,7 @@ inline Promise make_rejected_promise(E &&e) { Promise result; - result.reject(std::forward(e)); + result.Reject(std::forward(e)); return result; } diff --git a/include/sled/sled.h b/include/sled/sled.h index cbff3a8..29b822a 100644 --- a/include/sled/sled.h +++ b/include/sled/sled.h @@ -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" diff --git a/include/sled/units/time_delta.h b/include/sled/units/time_delta.h index 9752df5..b234516 100644 --- a/include/sled/units/time_delta.h +++ b/include/sled/units/time_delta.h @@ -9,6 +9,7 @@ #define SLED_UNITS_TIME_DELTA_H #include "sled/units/unit_base.h" +#include #include namespace sled { @@ -43,10 +44,10 @@ public: return FromValue(value); } - template - inline TimeDelta(std::chrono::duration duration) + template + inline TimeDelta(const std::chrono::duration &duration) { - *this = Micros(std::chrono::duration_cast(duration)); + *this = FromValue(std::chrono::duration_cast(duration).count()); } TimeDelta() = delete; diff --git a/src/futures/promise_test.cc b/src/futures/promise_test.cc index 0fbcf95..4efe3a4 100644 --- a/src/futures/promise_test.cc +++ b/src/futures/promise_test.cc @@ -19,3 +19,19 @@ TEST(Promise, Basic) }); p.Resolve(1); } + +TEST(Future, Basic) +{ + auto p = sled::Promise(); + 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); +}