feat add future
This commit is contained in:
parent
c0a2b73d0d
commit
190bbe15aa
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user