feat add future
This commit is contained in:
parent
c0a2b73d0d
commit
190bbe15aa
@ -238,6 +238,7 @@ private:
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
namespace promise_hpp {
|
namespace promise_hpp {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class promise final {
|
class promise final {
|
||||||
public:
|
public:
|
||||||
@ -261,6 +262,8 @@ public:
|
|||||||
|
|
||||||
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
|
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
|
||||||
|
|
||||||
|
promise GetFuture() const { return promise(*this); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// get
|
// get
|
||||||
//
|
//
|
||||||
@ -283,6 +286,11 @@ public:
|
|||||||
|
|
||||||
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(std::chrono::microseconds(timeout_duration.us()));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Rep, typename Period>
|
template<typename Rep, typename Period>
|
||||||
promise_wait_status WaitFor(const std::chrono::duration<Rep, Period> &timeout_duration) const
|
promise_wait_status WaitFor(const std::chrono::duration<Rep, Period> &timeout_duration) const
|
||||||
{
|
{
|
||||||
@ -628,6 +636,9 @@ private:
|
|||||||
std::vector<handler> handlers_;
|
std::vector<handler> handlers_;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using future = promise<T>;
|
||||||
}// namespace promise_hpp
|
}// namespace promise_hpp
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -660,16 +671,18 @@ public:
|
|||||||
|
|
||||||
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
|
friend bool operator!=(const promise &l, const promise &r) noexcept { return l.state_ != r.state_; }
|
||||||
|
|
||||||
|
promise GetFuture() const { return promise(*this); }
|
||||||
|
|
||||||
//
|
//
|
||||||
// get
|
// get
|
||||||
//
|
//
|
||||||
|
|
||||||
void get() const { state_->get(); }
|
void Get() const { state_->get(); }
|
||||||
|
|
||||||
void get_or_default() const
|
void GetOr() const
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
return get();
|
return Get();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
@ -679,16 +692,21 @@ public:
|
|||||||
// wait
|
// 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>
|
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);
|
return state_->wait_for(timeout_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Clock, typename 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);
|
return state_->wait_until(timeout_time);
|
||||||
}
|
}
|
||||||
@ -697,12 +715,12 @@ public:
|
|||||||
// resolve/reject
|
// 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>
|
template<typename E>
|
||||||
bool reject(E &&e)
|
bool Reject(E &&e)
|
||||||
{
|
{
|
||||||
return state_->reject(std::make_exception_ptr(std::forward<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>>
|
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;
|
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));
|
auto np = eggs::invoke(std::forward<decltype(f)>(f));
|
||||||
std::move(np)
|
std::move(np)
|
||||||
.then([n](auto &&...nvs) mutable { n.resolve(std::forward<decltype(nvs)>(nvs)...); })
|
.then([n](auto &&...nvs) mutable { n.resolve(std::forward<decltype(nvs)>(nvs)...); })
|
||||||
@ -727,36 +745,36 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResolveF>
|
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));
|
auto r = eggs::invoke(std::forward<decltype(f)>(f));
|
||||||
return make_all_promise(std::move(r));
|
return make_all_promise(std::move(r));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResolveF>
|
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));
|
auto r = eggs::invoke(std::forward<decltype(f)>(f));
|
||||||
return make_any_promise(std::move(r));
|
return make_any_promise(std::move(r));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResolveF>
|
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));
|
auto r = eggs::invoke(std::forward<decltype(f)>(f));
|
||||||
return make_race_promise(std::move(r));
|
return make_race_promise(std::move(r));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResolveF>
|
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));
|
auto r = eggs::invoke(std::forward<decltype(f)>(f));
|
||||||
return make_tuple_promise(std::move(r));
|
return make_tuple_promise(std::move(r));
|
||||||
});
|
});
|
||||||
@ -767,7 +785,7 @@ public:
|
|||||||
//
|
//
|
||||||
|
|
||||||
template<typename ResolveF, typename ResolveR = eggs::invoke_result_t<ResolveF>>
|
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;
|
promise<ResolveR> next;
|
||||||
|
|
||||||
@ -779,7 +797,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename ResolveF, typename RejectF, typename ResolveR = eggs::invoke_result_t<ResolveF>>
|
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;
|
promise<ResolveR> next;
|
||||||
|
|
||||||
@ -793,9 +811,9 @@ public:
|
|||||||
//
|
//
|
||||||
|
|
||||||
template<typename RejectF>
|
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>
|
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) {
|
[f = on_finally](std::exception_ptr e) {
|
||||||
eggs::invoke(std::move(f));
|
eggs::invoke(std::move(f));
|
||||||
std::rethrow_exception(e);
|
std::rethrow_exception(e);
|
||||||
@ -839,6 +857,16 @@ private:
|
|||||||
cond_var_.Wait(lock, [this]() { return status_ != status::pending; });
|
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>
|
template<typename Rep, typename Period>
|
||||||
promise_wait_status wait_for(const std::chrono::duration<Rep, Period> &timeout_duration) const
|
promise_wait_status wait_for(const std::chrono::duration<Rep, Period> &timeout_duration) const
|
||||||
{
|
{
|
||||||
@ -856,7 +884,8 @@ private:
|
|||||||
sled::MutexLock lock(&mutex_);
|
sled::MutexLock lock(&mutex_);
|
||||||
// std::unique_lock lock(mutex_);
|
// std::unique_lock lock(mutex_);
|
||||||
// return cond_var_.wait_until(lock, timeout_time, [this]() { return status_ != status::pending; })
|
// 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::no_timeout
|
||||||
: promise_wait_status::timeout;
|
: promise_wait_status::timeout;
|
||||||
}
|
}
|
||||||
@ -1048,7 +1077,7 @@ inline promise<void>
|
|||||||
make_resolved_promise()
|
make_resolved_promise()
|
||||||
{
|
{
|
||||||
promise<void> result;
|
promise<void> result;
|
||||||
result.resolve();
|
result.Resolve();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,7 +1099,7 @@ promise<void>
|
|||||||
make_rejected_promise(E &&e)
|
make_rejected_promise(E &&e)
|
||||||
{
|
{
|
||||||
promise<void> result;
|
promise<void> result;
|
||||||
result.reject(std::forward<E>(e));
|
result.Reject(std::forward<E>(e));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1314,6 +1343,9 @@ struct IsPromiseRet : promise_hpp::is_promise_r<TRet, TPromise> {};
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
using Promise = promise_hpp::promise<T>;
|
using Promise = promise_hpp::promise<T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Future = promise_hpp::future<T>;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline auto
|
inline auto
|
||||||
MakePromise() -> Promise<T>
|
MakePromise() -> Promise<T>
|
||||||
@ -1332,7 +1364,7 @@ inline auto
|
|||||||
MakeResolvedPromise() -> Promise<void>
|
MakeResolvedPromise() -> Promise<void>
|
||||||
{
|
{
|
||||||
Promise<void> result;
|
Promise<void> result;
|
||||||
result.resolve();
|
result.Resolve();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1348,7 +1380,7 @@ inline Promise<void>
|
|||||||
make_rejected_promise(E &&e)
|
make_rejected_promise(E &&e)
|
||||||
{
|
{
|
||||||
Promise<void> result;
|
Promise<void> result;
|
||||||
result.reject(std::forward<E>(e));
|
result.Reject(std::forward<E>(e));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@
|
|||||||
#include "sled/filesystem/path.h"
|
#include "sled/filesystem/path.h"
|
||||||
#include "sled/filesystem/temporary_file.h"
|
#include "sled/filesystem/temporary_file.h"
|
||||||
|
|
||||||
|
// futures
|
||||||
|
#include "sled/futures/promise.h"
|
||||||
|
|
||||||
// lang
|
// lang
|
||||||
#include "lang/attributes.h"
|
#include "lang/attributes.h"
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#define SLED_UNITS_TIME_DELTA_H
|
#define SLED_UNITS_TIME_DELTA_H
|
||||||
|
|
||||||
#include "sled/units/unit_base.h"
|
#include "sled/units/unit_base.h"
|
||||||
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace sled {
|
namespace sled {
|
||||||
@ -43,10 +44,10 @@ public:
|
|||||||
return FromValue(value);
|
return FromValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename V>
|
template<typename Clock, typename Duration>
|
||||||
inline TimeDelta(std::chrono::duration<T, V> 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;
|
TimeDelta() = delete;
|
||||||
|
@ -19,3 +19,19 @@ TEST(Promise, Basic)
|
|||||||
});
|
});
|
||||||
p.Resolve(1);
|
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…
x
Reference in New Issue
Block a user