mirror of
https://github.com/BlackMATov/promise.hpp.git
synced 2025-12-16 22:19:38 +07:00
@@ -26,7 +26,7 @@ namespace jobber_hpp
|
|||||||
timeout
|
timeout
|
||||||
};
|
};
|
||||||
|
|
||||||
class jobber_cancelled_exception : public std::runtime_error {
|
class jobber_cancelled_exception final : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
jobber_cancelled_exception()
|
jobber_cancelled_exception()
|
||||||
: std::runtime_error("jobber has stopped working") {}
|
: std::runtime_error("jobber has stopped working") {}
|
||||||
@@ -102,7 +102,7 @@ namespace jobber_hpp
|
|||||||
mutable std::condition_variable cond_var_;
|
mutable std::condition_variable cond_var_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class jobber::task : private noncopyable {
|
class jobber::task : private detail::noncopyable {
|
||||||
public:
|
public:
|
||||||
virtual ~task() noexcept = default;
|
virtual ~task() noexcept = default;
|
||||||
virtual void run() noexcept = 0;
|
virtual void run() noexcept = 0;
|
||||||
@@ -110,7 +110,7 @@ namespace jobber_hpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template < typename R, typename F, typename... Args >
|
template < typename R, typename F, typename... Args >
|
||||||
class jobber::concrete_task : public task {
|
class jobber::concrete_task final : public task {
|
||||||
F f_;
|
F f_;
|
||||||
std::tuple<Args...> args_;
|
std::tuple<Args...> args_;
|
||||||
promise<R> promise_;
|
promise<R> promise_;
|
||||||
@@ -123,7 +123,7 @@ namespace jobber_hpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template < typename F, typename... Args >
|
template < typename F, typename... Args >
|
||||||
class jobber::concrete_task<void, F, Args...> : public task {
|
class jobber::concrete_task<void, F, Args...> final : public task {
|
||||||
F f_;
|
F f_;
|
||||||
std::tuple<Args...> args_;
|
std::tuple<Args...> args_;
|
||||||
promise<void> promise_;
|
promise<void> promise_;
|
||||||
|
|||||||
@@ -79,11 +79,34 @@ namespace promise_hpp
|
|||||||
inline constexpr bool is_promise_r_v = is_promise_r<R, T>::value;
|
inline constexpr bool is_promise_r_v = is_promise_r<R, T>::value;
|
||||||
|
|
||||||
//
|
//
|
||||||
// detail
|
// promise_wait_status
|
||||||
//
|
//
|
||||||
|
|
||||||
namespace detail
|
enum class promise_wait_status {
|
||||||
{
|
no_timeout,
|
||||||
|
timeout
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// detail
|
||||||
|
//
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace promise_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
void destroy_in_place(T& ref) noexcept {
|
||||||
|
ref.~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T, typename... Args >
|
||||||
|
void construct_in_place(T& ref, Args&&... args)
|
||||||
|
noexcept(std::is_nothrow_constructible_v<T, Args...>) {
|
||||||
|
::new (std::addressof(ref)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
class noncopyable {
|
class noncopyable {
|
||||||
public:
|
public:
|
||||||
noncopyable(const noncopyable&) = delete;
|
noncopyable(const noncopyable&) = delete;
|
||||||
@@ -98,39 +121,34 @@ namespace promise_hpp
|
|||||||
public:
|
public:
|
||||||
storage() = default;
|
storage() = default;
|
||||||
|
|
||||||
~storage()
|
~storage() noexcept {
|
||||||
noexcept(std::is_nothrow_destructible_v<T>) {
|
|
||||||
if ( initialized_ ) {
|
if ( initialized_ ) {
|
||||||
ptr_()->~T();
|
destroy_in_place(*ptr_());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(T&& value)
|
storage& operator=(T&& value)
|
||||||
noexcept(std::is_nothrow_move_constructible_v<T>) {
|
noexcept(std::is_nothrow_move_constructible_v<T>) {
|
||||||
assert(!initialized_);
|
assert(!initialized_);
|
||||||
::new(ptr_()) T(std::move(value));
|
construct_in_place(*ptr_(), std::move(value));
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(const T& value)
|
storage& operator=(const T& value)
|
||||||
noexcept(std::is_nothrow_copy_constructible_v<T>) {
|
noexcept(std::is_nothrow_copy_constructible_v<T>) {
|
||||||
assert(!initialized_);
|
assert(!initialized_);
|
||||||
::new(ptr_()) T(value);
|
construct_in_place(*ptr_(), value);
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T get()
|
T& operator*() noexcept {
|
||||||
noexcept(std::is_nothrow_move_constructible_v<T>) {
|
|
||||||
assert(initialized_);
|
|
||||||
return std::move(*ptr_());
|
|
||||||
}
|
|
||||||
|
|
||||||
T& value() noexcept {
|
|
||||||
assert(initialized_);
|
assert(initialized_);
|
||||||
return *ptr_();
|
return *ptr_();
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& value() const noexcept {
|
const T& operator*() const noexcept {
|
||||||
assert(initialized_);
|
assert(initialized_);
|
||||||
return *ptr_();
|
return *ptr_();
|
||||||
}
|
}
|
||||||
@@ -153,23 +171,19 @@ namespace promise_hpp
|
|||||||
storage() = default;
|
storage() = default;
|
||||||
~storage() = default;
|
~storage() = default;
|
||||||
|
|
||||||
void set(T& value) noexcept {
|
storage& operator=(T& value) noexcept {
|
||||||
assert(!initialized_);
|
assert(!initialized_);
|
||||||
value_ = &value;
|
value_ = &value;
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& get() noexcept {
|
T& operator*() noexcept {
|
||||||
assert(initialized_);
|
assert(initialized_);
|
||||||
return *value_;
|
return *value_;
|
||||||
}
|
}
|
||||||
|
|
||||||
T& value() noexcept {
|
const T& operator*() const noexcept {
|
||||||
assert(initialized_);
|
|
||||||
return *value_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T& value() const noexcept {
|
|
||||||
assert(initialized_);
|
assert(initialized_);
|
||||||
return *value_;
|
return *value_;
|
||||||
}
|
}
|
||||||
@@ -177,16 +191,6 @@ namespace promise_hpp
|
|||||||
T* value_{nullptr};
|
T* value_{nullptr};
|
||||||
bool initialized_ = false;
|
bool initialized_ = false;
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// promise_wait_status
|
|
||||||
//
|
|
||||||
|
|
||||||
enum class promise_wait_status {
|
|
||||||
no_timeout,
|
|
||||||
timeout
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -299,10 +303,10 @@ namespace promise_hpp
|
|||||||
then([
|
then([
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](auto&&... vs) mutable {
|
](auto&& v) mutable {
|
||||||
auto np = std::invoke(
|
auto np = std::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f),
|
||||||
std::forward<decltype(vs)>(vs)...);
|
std::forward<decltype(v)>(v));
|
||||||
std::move(np).then([n](auto&&... nvs) mutable {
|
std::move(np).then([n](auto&&... nvs) mutable {
|
||||||
n.resolve(std::forward<decltype(nvs)>(nvs)...);
|
n.resolve(std::forward<decltype(nvs)>(nvs)...);
|
||||||
}).except([n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
@@ -327,6 +331,18 @@ namespace promise_hpp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename ResolveF >
|
||||||
|
auto then_any(ResolveF&& on_resolve) {
|
||||||
|
return then([
|
||||||
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
|
](auto&& v) mutable {
|
||||||
|
auto r = std::invoke(
|
||||||
|
std::forward<decltype(f)>(f),
|
||||||
|
std::forward<decltype(v)>(v));
|
||||||
|
return make_any_promise(std::move(r));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template < typename ResolveF >
|
template < typename ResolveF >
|
||||||
auto then_race(ResolveF&& on_resolve) {
|
auto then_race(ResolveF&& on_resolve) {
|
||||||
return then([
|
return then([
|
||||||
@@ -417,7 +433,7 @@ namespace promise_hpp
|
|||||||
std::rethrow_exception(exception_);
|
std::rethrow_exception(exception_);
|
||||||
}
|
}
|
||||||
assert(status_ == status::resolved);
|
assert(status_ == status::resolved);
|
||||||
return storage_.value();
|
return *storage_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait() const noexcept {
|
void wait() const noexcept {
|
||||||
@@ -449,7 +465,7 @@ namespace promise_hpp
|
|||||||
if ( status_ != status::pending ) {
|
if ( status_ != status::pending ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
storage_.set(std::forward<U>(value));
|
storage_ = std::forward<U>(value);
|
||||||
status_ = status::resolved;
|
status_ = status::resolved;
|
||||||
invoke_resolve_handlers_();
|
invoke_resolve_handlers_();
|
||||||
cond_var_.notify_all();
|
cond_var_.notify_all();
|
||||||
@@ -553,7 +569,7 @@ namespace promise_hpp
|
|||||||
if ( status_ == status::resolved ) {
|
if ( status_ == status::resolved ) {
|
||||||
std::invoke(
|
std::invoke(
|
||||||
std::forward<ResolveF>(resolve),
|
std::forward<ResolveF>(resolve),
|
||||||
storage_.value());
|
*storage_);
|
||||||
} else if ( status_ == status::rejected ) {
|
} else if ( status_ == status::rejected ) {
|
||||||
std::invoke(
|
std::invoke(
|
||||||
std::forward<RejectF>(reject),
|
std::forward<RejectF>(reject),
|
||||||
@@ -567,7 +583,7 @@ namespace promise_hpp
|
|||||||
|
|
||||||
void invoke_resolve_handlers_() noexcept {
|
void invoke_resolve_handlers_() noexcept {
|
||||||
for ( const auto& h : handlers_ ) {
|
for ( const auto& h : handlers_ ) {
|
||||||
h.resolve_(storage_.value());
|
h.resolve_(*storage_);
|
||||||
}
|
}
|
||||||
handlers_.clear();
|
handlers_.clear();
|
||||||
}
|
}
|
||||||
@@ -599,8 +615,8 @@ namespace promise_hpp
|
|||||||
reject_t reject_;
|
reject_t reject_;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<handler> handlers_;
|
|
||||||
detail::storage<T> storage_;
|
detail::storage<T> storage_;
|
||||||
|
std::vector<handler> handlers_;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -713,10 +729,9 @@ namespace promise_hpp
|
|||||||
then([
|
then([
|
||||||
n = next,
|
n = next,
|
||||||
f = std::forward<ResolveF>(on_resolve)
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
](auto&&... vs) mutable {
|
]() mutable {
|
||||||
auto np = std::invoke(
|
auto np = std::invoke(
|
||||||
std::forward<decltype(f)>(f),
|
std::forward<decltype(f)>(f));
|
||||||
std::forward<decltype(vs)>(vs)...);
|
|
||||||
std::move(np).then([n](auto&&... nvs) mutable {
|
std::move(np).then([n](auto&&... nvs) mutable {
|
||||||
n.resolve(std::forward<decltype(nvs)>(nvs)...);
|
n.resolve(std::forward<decltype(nvs)>(nvs)...);
|
||||||
}).except([n](std::exception_ptr e) mutable {
|
}).except([n](std::exception_ptr e) mutable {
|
||||||
@@ -740,6 +755,17 @@ namespace promise_hpp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename ResolveF >
|
||||||
|
auto then_any(ResolveF&& on_resolve) {
|
||||||
|
return then([
|
||||||
|
f = std::forward<ResolveF>(on_resolve)
|
||||||
|
]() mutable {
|
||||||
|
auto r = std::invoke(
|
||||||
|
std::forward<decltype(f)>(f));
|
||||||
|
return make_any_promise(std::move(r));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template < typename ResolveF >
|
template < typename ResolveF >
|
||||||
auto then_race(ResolveF&& on_resolve) {
|
auto then_race(ResolveF&& on_resolve) {
|
||||||
return then([
|
return then([
|
||||||
@@ -1092,34 +1118,6 @@ namespace promise_hpp
|
|||||||
// make_all_promise
|
// make_all_promise
|
||||||
//
|
//
|
||||||
|
|
||||||
namespace impl
|
|
||||||
{
|
|
||||||
template < typename ResultType >
|
|
||||||
class all_promise_context_t final : private detail::noncopyable {
|
|
||||||
public:
|
|
||||||
all_promise_context_t(std::size_t count)
|
|
||||||
: results_(count) {}
|
|
||||||
|
|
||||||
template < typename T >
|
|
||||||
bool apply_result(std::size_t index, T&& value) {
|
|
||||||
results_[index].set(std::forward<T>(value));
|
|
||||||
return ++counter_ == results_.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ResultType> get_results() {
|
|
||||||
std::vector<ResultType> ret;
|
|
||||||
ret.reserve(results_.size());
|
|
||||||
for ( auto&& v : results_ ) {
|
|
||||||
ret.push_back(v.get());
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::atomic_size_t counter_{0};
|
|
||||||
std::vector<detail::storage<ResultType>> results_;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Iter
|
template < typename Iter
|
||||||
, typename SubPromise = typename std::iterator_traits<Iter>::value_type
|
, typename SubPromise = typename std::iterator_traits<Iter>::value_type
|
||||||
, typename SubPromiseResult = typename SubPromise::value_type
|
, typename SubPromiseResult = typename SubPromise::value_type
|
||||||
@@ -1129,18 +1127,32 @@ namespace promise_hpp
|
|||||||
if ( begin == end ) {
|
if ( begin == end ) {
|
||||||
return make_resolved_promise(ResultPromiseValueType());
|
return make_resolved_promise(ResultPromiseValueType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct context_t {
|
||||||
|
std::atomic_size_t success_counter{0u};
|
||||||
|
std::vector<detail::storage<SubPromiseResult>> results;
|
||||||
|
context_t(std::size_t count)
|
||||||
|
: success_counter(count)
|
||||||
|
, results(count) {}
|
||||||
|
};
|
||||||
|
|
||||||
return make_promise<ResultPromiseValueType>([begin, end](auto&& resolver, auto&& rejector){
|
return make_promise<ResultPromiseValueType>([begin, end](auto&& resolver, auto&& rejector){
|
||||||
std::size_t result_index = 0;
|
std::size_t result_index = 0;
|
||||||
auto context = std::make_shared<impl::all_promise_context_t<
|
auto context = std::make_shared<context_t>(std::distance(begin, end));
|
||||||
SubPromiseResult>>(std::distance(begin, end));
|
|
||||||
for ( Iter iter = begin; iter != end; ++iter, ++result_index ) {
|
for ( Iter iter = begin; iter != end; ++iter, ++result_index ) {
|
||||||
(*iter).then([
|
(*iter).then([
|
||||||
context,
|
context,
|
||||||
resolver,
|
resolver,
|
||||||
result_index
|
result_index
|
||||||
](auto&& v) mutable {
|
](auto&& v) mutable {
|
||||||
if ( context->apply_result(result_index, std::forward<decltype(v)>(v)) ) {
|
context->results[result_index] = std::forward<decltype(v)>(v);
|
||||||
resolver(context->get_results());
|
if ( !--context->success_counter ) {
|
||||||
|
std::vector<SubPromiseResult> results;
|
||||||
|
results.reserve(context->results.size());
|
||||||
|
for ( auto&& r : context->results ) {
|
||||||
|
results.push_back(std::move(*r));
|
||||||
|
}
|
||||||
|
resolver(std::move(results));
|
||||||
}
|
}
|
||||||
}).except(rejector);
|
}).except(rejector);
|
||||||
}
|
}
|
||||||
@@ -1154,6 +1166,46 @@ namespace promise_hpp
|
|||||||
std::end(container));
|
std::end(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// make_any_promise
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename Iter
|
||||||
|
, typename SubPromise = typename std::iterator_traits<Iter>::value_type
|
||||||
|
, typename SubPromiseResult = typename SubPromise::value_type >
|
||||||
|
promise<SubPromiseResult>
|
||||||
|
make_any_promise(Iter begin, Iter end) {
|
||||||
|
if ( begin == end ) {
|
||||||
|
throw std::logic_error("at least one input promise must be provided for make_any_promise");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct context_t {
|
||||||
|
std::atomic_size_t failure_counter{0u};
|
||||||
|
context_t(std::size_t count)
|
||||||
|
: failure_counter(count) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
return make_promise<SubPromiseResult>([begin, end](auto&& resolver, auto&& rejector){
|
||||||
|
auto context = std::make_shared<context_t>(std::distance(begin, end));
|
||||||
|
for ( Iter iter = begin; iter != end; ++iter ) {
|
||||||
|
(*iter).then([resolver](auto&& v) mutable {
|
||||||
|
resolver(std::forward<decltype(v)>(v));
|
||||||
|
}).except([context, rejector](std::exception_ptr e) mutable {
|
||||||
|
if ( !--context->failure_counter ) {
|
||||||
|
rejector(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename Container >
|
||||||
|
auto make_any_promise(Container&& container) {
|
||||||
|
return make_any_promise(
|
||||||
|
std::begin(container),
|
||||||
|
std::end(container));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// make_race_promise
|
// make_race_promise
|
||||||
//
|
//
|
||||||
@@ -1166,6 +1218,7 @@ namespace promise_hpp
|
|||||||
if ( begin == end ) {
|
if ( begin == end ) {
|
||||||
throw std::logic_error("at least one input promise must be provided for make_race_promise");
|
throw std::logic_error("at least one input promise must be provided for make_race_promise");
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_promise<SubPromiseResult>([begin, end](auto&& resolver, auto&& rejector){
|
return make_promise<SubPromiseResult>([begin, end](auto&& resolver, auto&& rejector){
|
||||||
for ( Iter iter = begin; iter != end; ++iter ) {
|
for ( Iter iter = begin; iter != end; ++iter ) {
|
||||||
(*iter)
|
(*iter)
|
||||||
@@ -1205,11 +1258,11 @@ namespace promise_hpp
|
|||||||
using tuple_promise_result_t = typename tuple_promise_result<Tuple>::type;
|
using tuple_promise_result_t = typename tuple_promise_result<Tuple>::type;
|
||||||
|
|
||||||
template < typename... ResultTypes >
|
template < typename... ResultTypes >
|
||||||
class tuple_promise_context_t {
|
class tuple_promise_context_t final : private detail::noncopyable {
|
||||||
public:
|
public:
|
||||||
template < std::size_t N, typename T >
|
template < std::size_t N, typename T >
|
||||||
bool apply_result(T&& value) {
|
bool apply_result(T&& value) {
|
||||||
std::get<N>(results_).set(std::forward<T>(value));
|
std::get<N>(results_) = std::forward<T>(value);
|
||||||
return ++counter_ == sizeof...(ResultTypes);
|
return ++counter_ == sizeof...(ResultTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1220,7 +1273,7 @@ namespace promise_hpp
|
|||||||
private:
|
private:
|
||||||
template < std::size_t... Is >
|
template < std::size_t... Is >
|
||||||
std::tuple<ResultTypes...> get_results_impl(std::index_sequence<Is...>) {
|
std::tuple<ResultTypes...> get_results_impl(std::index_sequence<Is...>) {
|
||||||
return {std::get<Is>(results_).get()...};
|
return {std::move(*std::get<Is>(results_))...};
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::atomic_size_t counter_{0};
|
std::atomic_size_t counter_{0};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace scheduler_hpp
|
|||||||
cancelled
|
cancelled
|
||||||
};
|
};
|
||||||
|
|
||||||
class scheduler_cancelled_exception : public std::runtime_error {
|
class scheduler_cancelled_exception final : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
scheduler_cancelled_exception()
|
scheduler_cancelled_exception()
|
||||||
: std::runtime_error("scheduler has stopped working") {}
|
: std::runtime_error("scheduler has stopped working") {}
|
||||||
@@ -82,7 +82,7 @@ namespace scheduler_hpp
|
|||||||
mutable std::condition_variable cond_var_;
|
mutable std::condition_variable cond_var_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class scheduler::task : private noncopyable {
|
class scheduler::task : private detail::noncopyable {
|
||||||
public:
|
public:
|
||||||
virtual ~task() noexcept = default;
|
virtual ~task() noexcept = default;
|
||||||
virtual void run() noexcept = 0;
|
virtual void run() noexcept = 0;
|
||||||
@@ -90,7 +90,7 @@ namespace scheduler_hpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template < typename R, typename F, typename... Args >
|
template < typename R, typename F, typename... Args >
|
||||||
class scheduler::concrete_task : public task {
|
class scheduler::concrete_task final : public task {
|
||||||
F f_;
|
F f_;
|
||||||
std::tuple<Args...> args_;
|
std::tuple<Args...> args_;
|
||||||
promise<R> promise_;
|
promise<R> promise_;
|
||||||
@@ -103,7 +103,7 @@ namespace scheduler_hpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template < typename F, typename... Args >
|
template < typename F, typename... Args >
|
||||||
class scheduler::concrete_task<void, F, Args...> : public task {
|
class scheduler::concrete_task<void, F, Args...> final : public task {
|
||||||
F f_;
|
F f_;
|
||||||
std::tuple<Args...> args_;
|
std::tuple<Args...> args_;
|
||||||
promise<void> promise_;
|
promise<void> promise_;
|
||||||
|
|||||||
@@ -205,7 +205,7 @@ TEST_CASE("promise") {
|
|||||||
SECTION("resolved_ref") {
|
SECTION("resolved_ref") {
|
||||||
{
|
{
|
||||||
int* check_42_int = nullptr;
|
int* check_42_int = nullptr;
|
||||||
auto p = pr::promise<int&>();
|
auto p = pr::promise<std::reference_wrapper<int>>();
|
||||||
int i = 42;
|
int i = 42;
|
||||||
p.resolve(i);
|
p.resolve(i);
|
||||||
p.then([&check_42_int](int& value) mutable {
|
p.then([&check_42_int](int& value) mutable {
|
||||||
@@ -216,7 +216,7 @@ TEST_CASE("promise") {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
const int* check_42_int = nullptr;
|
const int* check_42_int = nullptr;
|
||||||
auto p = pr::promise<const int&>();
|
auto p = pr::promise<std::reference_wrapper<const int>>();
|
||||||
const int i = 42;
|
const int i = 42;
|
||||||
p.resolve(i);
|
p.resolve(i);
|
||||||
p.then([&check_42_int](const int& value) mutable {
|
p.then([&check_42_int](const int& value) mutable {
|
||||||
@@ -692,9 +692,23 @@ TEST_CASE("promise") {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
bool all_is_ok = false;
|
bool all_is_ok = false;
|
||||||
auto p = pr::make_all_promise(std::vector<pr::promise<int>>{
|
auto p = pr::make_resolved_promise().then_all([](){
|
||||||
|
return std::vector<pr::promise<int>>{
|
||||||
pr::make_resolved_promise(32),
|
pr::make_resolved_promise(32),
|
||||||
pr::make_resolved_promise(10)
|
pr::make_resolved_promise(10)};
|
||||||
|
}).then([&all_is_ok](const std::vector<int>& c){
|
||||||
|
all_is_ok = (2 == c.size())
|
||||||
|
&& c[0] == 32
|
||||||
|
&& c[1] == 10;
|
||||||
|
});
|
||||||
|
REQUIRE(all_is_ok);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool all_is_ok = false;
|
||||||
|
auto p = pr::make_resolved_promise(1).then_all([](int){
|
||||||
|
return std::vector<pr::promise<int>>{
|
||||||
|
pr::make_resolved_promise(32),
|
||||||
|
pr::make_resolved_promise(10)};
|
||||||
}).then([&all_is_ok](const std::vector<int>& c){
|
}).then([&all_is_ok](const std::vector<int>& c){
|
||||||
all_is_ok = (2 == c.size())
|
all_is_ok = (2 == c.size())
|
||||||
&& c[0] == 32
|
&& c[0] == 32
|
||||||
@@ -749,6 +763,60 @@ TEST_CASE("promise") {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SECTION("make_any_promise") {
|
||||||
|
REQUIRE_THROWS_AS(
|
||||||
|
pr::make_any_promise(std::vector<pr::promise<int>>{}),
|
||||||
|
std::logic_error);
|
||||||
|
{
|
||||||
|
auto p = pr::make_resolved_promise().then_any([](){
|
||||||
|
return std::vector<pr::promise<int>>{
|
||||||
|
pr::make_resolved_promise(32),
|
||||||
|
pr::make_resolved_promise(10)};
|
||||||
|
}).then([](int i){
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
REQUIRE(p.get() == 32);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto p = pr::make_resolved_promise(1).then_any([](int){
|
||||||
|
return std::vector<pr::promise<int>>{
|
||||||
|
pr::make_resolved_promise(32),
|
||||||
|
pr::make_resolved_promise(10)};
|
||||||
|
}).then([](int i){
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
REQUIRE(p.get() == 32);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto p = pr::make_any_promise(std::vector<pr::promise<int>>{
|
||||||
|
pr::make_resolved_promise(32),
|
||||||
|
pr::make_rejected_promise<int>(std::logic_error("hello fail"))
|
||||||
|
}).then([](int i){
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
REQUIRE(p.get() == 32);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto p = pr::make_any_promise(std::vector<pr::promise<int>>{
|
||||||
|
pr::make_rejected_promise<int>(std::logic_error("hello fail")),
|
||||||
|
pr::make_resolved_promise(32)
|
||||||
|
}).then([](int i){
|
||||||
|
return i;
|
||||||
|
});
|
||||||
|
REQUIRE(p.get() == 32);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
bool all_is_ok = false;
|
||||||
|
auto p = pr::make_any_promise(std::vector<pr::promise<int>>{
|
||||||
|
pr::make_rejected_promise<int>(std::logic_error("hello fail")),
|
||||||
|
pr::make_rejected_promise<int>(std::logic_error("hello fail"))
|
||||||
|
}).except([&all_is_ok](std::exception_ptr e){
|
||||||
|
all_is_ok = true;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
REQUIRE(all_is_ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
SECTION("make_race_promise") {
|
SECTION("make_race_promise") {
|
||||||
{
|
{
|
||||||
auto p1 = pr::promise<int>();
|
auto p1 = pr::promise<int>();
|
||||||
@@ -892,8 +960,8 @@ TEST_CASE("promise") {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto p1 = pr::promise<int&>();
|
auto p1 = pr::promise<std::reference_wrapper<int>>();
|
||||||
auto p2 = pr::promise<float&>();
|
auto p2 = pr::promise<std::reference_wrapper<float>>();
|
||||||
auto p3 = pr::make_tuple_promise(std::make_tuple(p1, p2));
|
auto p3 = pr::make_tuple_promise(std::make_tuple(p1, p2));
|
||||||
|
|
||||||
int i = 10;
|
int i = 10;
|
||||||
|
|||||||
Reference in New Issue
Block a user