mirror of
https://github.com/BlackMATov/promise.hpp.git
synced 2025-12-16 22:19:38 +07:00
little storage refactoring
This commit is contained in:
@@ -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_;
|
||||||
}
|
}
|
||||||
@@ -179,16 +193,6 @@ namespace promise_hpp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// promise_wait_status
|
|
||||||
//
|
|
||||||
|
|
||||||
enum class promise_wait_status {
|
|
||||||
no_timeout,
|
|
||||||
timeout
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// promise<T>
|
// promise<T>
|
||||||
@@ -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 {
|
||||||
@@ -417,7 +421,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 +453,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 +557,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 +571,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 +603,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 +717,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 {
|
||||||
@@ -1102,7 +1105,7 @@ namespace promise_hpp
|
|||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
bool apply_result(std::size_t index, T&& value) {
|
bool apply_result(std::size_t index, T&& value) {
|
||||||
results_[index].set(std::forward<T>(value));
|
results_[index] = std::forward<T>(value);
|
||||||
return ++counter_ == results_.size();
|
return ++counter_ == results_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1110,7 +1113,7 @@ namespace promise_hpp
|
|||||||
std::vector<ResultType> ret;
|
std::vector<ResultType> ret;
|
||||||
ret.reserve(results_.size());
|
ret.reserve(results_.size());
|
||||||
for ( auto&& v : results_ ) {
|
for ( auto&& v : results_ ) {
|
||||||
ret.push_back(v.get());
|
ret.push_back(std::move(*v));
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1205,11 +1208,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 +1223,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 {
|
||||||
@@ -892,8 +892,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