diff options
| author | levlam <levlam@telegram.org> | 2022-06-27 13:30:18 +0300 |
|---|---|---|
| committer | levlam <levlam@telegram.org> | 2022-06-27 13:30:18 +0300 |
| commit | 32bac7bd24202c717a7f4ae119cc7dec48d4b83a (patch) | |
| tree | 47f047b268e8c268a67808e99247e1edda2d7d3b /tdactor | |
| parent | da2e504566d5f8397c4eef573f4e4931ca6a9bef (diff) | |
Move Promise to tdutils.
Diffstat (limited to 'tdactor')
| -rw-r--r-- | tdactor/td/actor/MultiPromise.cpp | 2 | ||||
| -rw-r--r-- | tdactor/td/actor/MultiPromise.h | 1 | ||||
| -rw-r--r-- | tdactor/td/actor/PromiseFuture.h | 385 | ||||
| -rw-r--r-- | tdactor/td/actor/SleepActor.h | 2 | ||||
| -rw-r--r-- | tdactor/test/actors_simple.cpp | 1 |
5 files changed, 7 insertions, 384 deletions
diff --git a/tdactor/td/actor/MultiPromise.cpp b/tdactor/td/actor/MultiPromise.cpp index 5bf8d40bd..f78e0f016 100644 --- a/tdactor/td/actor/MultiPromise.cpp +++ b/tdactor/td/actor/MultiPromise.cpp @@ -28,7 +28,7 @@ Promise<Unit> MultiPromiseActor::get_promise() { future.set_event(EventCreator::raw(actor_id(), nullptr)); futures_.emplace_back(std::move(future)); LOG(DEBUG) << "Get promise #" << futures_.size() << " for " << name_; - return PromiseCreator::from_promise_actor(std::move(promise)); + return create_promise_from_promise_actor(std::move(promise)); } void MultiPromiseActor::raw_event(const Event::Raw &event) { diff --git a/tdactor/td/actor/MultiPromise.h b/tdactor/td/actor/MultiPromise.h index 88ac09e52..73b24d5d1 100644 --- a/tdactor/td/actor/MultiPromise.h +++ b/tdactor/td/actor/MultiPromise.h @@ -10,6 +10,7 @@ #include "td/actor/PromiseFuture.h" #include "td/utils/common.h" +#include "td/utils/Promise.h" #include "td/utils/Status.h" namespace td { diff --git a/tdactor/td/actor/PromiseFuture.h b/tdactor/td/actor/PromiseFuture.h index fb81bced1..1a8940558 100644 --- a/tdactor/td/actor/PromiseFuture.h +++ b/tdactor/td/actor/PromiseFuture.h @@ -8,282 +8,10 @@ #include "td/actor/actor.h" -#include "td/utils/CancellationToken.h" -#include "td/utils/Closure.h" #include "td/utils/common.h" -#include "td/utils/invoke.h" -#include "td/utils/logging.h" -#include "td/utils/MovableValue.h" -#include "td/utils/ScopeGuard.h" -#include "td/utils/Status.h" - -#include <tuple> -#include <type_traits> -#include <utility> +#include "td/utils/Promise.h" namespace td { - -template <class T = Unit> -class PromiseInterface { - public: - PromiseInterface() = default; - PromiseInterface(const PromiseInterface &) = delete; - PromiseInterface &operator=(const PromiseInterface &) = delete; - PromiseInterface(PromiseInterface &&) = default; - PromiseInterface &operator=(PromiseInterface &&) = default; - virtual ~PromiseInterface() = default; - - virtual void set_value(T &&value) { - set_result(std::move(value)); - } - virtual void set_error(Status &&error) { - set_result(std::move(error)); - } - virtual void set_result(Result<T> &&result) { - if (result.is_ok()) { - set_value(result.move_as_ok()); - } else { - set_error(result.move_as_error()); - } - } - - virtual bool is_cancellable() const { - return false; - } - virtual bool is_canceled() const { - return false; - } -}; - -namespace detail { - -template <typename T> -struct GetArg final : public GetArg<decltype(&T::operator())> {}; - -template <class C, class R, class Arg> -class GetArg<R (C::*)(Arg)> { - public: - using type = Arg; -}; -template <class C, class R, class Arg> -class GetArg<R (C::*)(Arg) const> { - public: - using type = Arg; -}; - -template <class T> -using get_arg_t = std::decay_t<typename GetArg<T>::type>; - -template <class T> -struct DropResult { - using type = T; -}; - -template <class T> -struct DropResult<Result<T>> { - using type = T; -}; - -template <class T> -using drop_result_t = typename DropResult<T>::type; - -template <class ValueT, class FunctionT> -class LambdaPromise : public PromiseInterface<ValueT> { - enum class State : int32 { Empty, Ready, Complete }; - - public: - void set_value(ValueT &&value) override { - CHECK(state_.get() == State::Ready); - func_(std::move(value)); - state_ = State::Complete; - } - - void set_error(Status &&error) override { - if (state_.get() == State::Ready) { - do_error(std::move(error)); - state_ = State::Complete; - } - } - LambdaPromise(const LambdaPromise &other) = delete; - LambdaPromise &operator=(const LambdaPromise &other) = delete; - LambdaPromise(LambdaPromise &&other) = default; - LambdaPromise &operator=(LambdaPromise &&other) = default; - ~LambdaPromise() override { - if (state_.get() == State::Ready) { - do_error(Status::Error("Lost promise")); - } - } - - template <class FromT> - explicit LambdaPromise(FromT &&func) : func_(std::forward<FromT>(func)), state_(State::Ready) { - } - - private: - FunctionT func_; - MovableValue<State> state_{State::Empty}; - - template <class F = FunctionT> - std::enable_if_t<is_callable<F, Result<ValueT>>::value, void> do_error(Status &&status) { - func_(Result<ValueT>(std::move(status))); - } - template <class Y, class F = FunctionT> - std::enable_if_t<!is_callable<F, Result<ValueT>>::value, void> do_error(Y &&status) { - func_(Auto()); - } -}; -} // namespace detail - -template <class T> -class SafePromise; - -template <class T = Unit> -class Promise; - -template <class T> -struct is_promise_interface : std::false_type {}; - -template <class U> -struct is_promise_interface<PromiseInterface<U>> : std::true_type {}; - -template <class U> -struct is_promise_interface<Promise<U>> : std::true_type {}; - -template <class T> -struct is_promise_interface_ptr : std::false_type {}; - -template <class U> -struct is_promise_interface_ptr<unique_ptr<U>> : std::true_type {}; - -template <class T = void, class F = void, std::enable_if_t<std::is_same<T, void>::value, bool> has_t = false> -auto lambda_promise(F &&f) { - return detail::LambdaPromise<detail::drop_result_t<detail::get_arg_t<std::decay_t<F>>>, std::decay_t<F>>( - std::forward<F>(f)); -} -template <class T = void, class F = void, std::enable_if_t<!std::is_same<T, void>::value, bool> has_t = true> -auto lambda_promise(F &&f) { - return detail::LambdaPromise<T, std::decay_t<F>>(std::forward<F>(f)); -} - -template <class T, class F, - std::enable_if_t<is_promise_interface<std::decay_t<F>>::value, bool> from_promise_interface = true> -auto &&promise_interface(F &&f) { - return std::forward<F>(f); -} - -template <class T, class F, - std::enable_if_t<!is_promise_interface<std::decay_t<F>>::value, bool> from_promise_interface = false> -auto promise_interface(F &&f) { - return lambda_promise<T>(std::forward<F>(f)); -} - -template <class T, class F, - std::enable_if_t<is_promise_interface_ptr<std::decay_t<F>>::value, bool> from_promise_interface = true> -auto promise_interface_ptr(F &&f) { - return std::forward<F>(f); -} - -template <class T, class F, - std::enable_if_t<!is_promise_interface_ptr<std::decay_t<F>>::value, bool> from_promise_interface = false> -auto promise_interface_ptr(F &&f) { - return td::make_unique<std::decay_t<decltype(promise_interface<T>(std::forward<F>(f)))>>( - promise_interface<T>(std::forward<F>(f))); -} - -template <class T> -class Promise { - public: - void set_value(T &&value) { - if (!promise_) { - return; - } - promise_->set_value(std::move(value)); - promise_.reset(); - } - void set_error(Status &&error) { - if (!promise_) { - return; - } - promise_->set_error(std::move(error)); - promise_.reset(); - } - void set_result(Result<T> &&result) { - if (!promise_) { - return; - } - promise_->set_result(std::move(result)); - promise_.reset(); - } - void reset() { - promise_.reset(); - } - bool is_cancellable() const { - if (!promise_) { - return false; - } - return promise_->is_cancellable(); - } - bool is_canceled() const { - if (!promise_) { - return false; - } - return promise_->is_canceled(); - } - unique_ptr<PromiseInterface<T>> release() { - return std::move(promise_); - } - - Promise() = default; - explicit Promise(unique_ptr<PromiseInterface<T>> promise) : promise_(std::move(promise)) { - } - Promise(Auto) { - } - Promise(SafePromise<T> &&other); - Promise &operator=(SafePromise<T> &&other); - template <class F, std::enable_if_t<!std::is_same<std::decay_t<F>, Promise>::value, int> = 0> - Promise(F &&f) : promise_(promise_interface_ptr<T>(std::forward<F>(f))) { - } - - explicit operator bool() { - return static_cast<bool>(promise_); - } - - private: - unique_ptr<PromiseInterface<T>> promise_; -}; - - -template <class T = Unit> -class SafePromise { - public: - SafePromise(Promise<T> promise, Result<T> result) : promise_(std::move(promise)), result_(std::move(result)) { - } - SafePromise(const SafePromise &other) = delete; - SafePromise &operator=(const SafePromise &other) = delete; - SafePromise(SafePromise &&other) = default; - SafePromise &operator=(SafePromise &&other) = default; - ~SafePromise() { - if (promise_) { - promise_.set_result(std::move(result_)); - } - } - Promise<T> release() { - return std::move(promise_); - } - - private: - Promise<T> promise_; - Result<T> result_; -}; - -template <class T> -Promise<T>::Promise(SafePromise<T> &&other) : Promise(other.release()) { -} -template <class T> -Promise<T> &Promise<T>::operator=(SafePromise<T> &&other) { - *this = other.release(); - return *this; -} - namespace detail { class EventPromise final : public PromiseInterface<Unit> { @@ -323,40 +51,6 @@ class EventPromise final : public PromiseInterface<Unit> { } } }; - -template <class PromiseT> -class CancellablePromise final : public PromiseT { - public: - template <class... ArgsT> - CancellablePromise(CancellationToken cancellation_token, ArgsT &&...args) - : PromiseT(std::forward<ArgsT>(args)...), cancellation_token_(std::move(cancellation_token)) { - } - bool is_cancellable() const final { - return true; - } - bool is_canceled() const final { - return static_cast<bool>(cancellation_token_); - } - - private: - CancellationToken cancellation_token_; -}; - -template <class... ArgsT> -class JoinPromise final : public PromiseInterface<Unit> { - public: - explicit JoinPromise(ArgsT &&...arg) : promises_(std::forward<ArgsT>(arg)...) { - } - void set_value(Unit &&) final { - tuple_for_each(promises_, [](auto &promise) { promise.set_value(Unit()); }); - } - void set_error(Status &&error) final { - tuple_for_each(promises_, [&error](auto &promise) { promise.set_error(error.clone()); }); - } - - private: - std::tuple<std::decay_t<ArgsT>...> promises_; -}; } // namespace detail inline Promise<Unit> create_event_promise(EventFull &&ok) { @@ -367,31 +61,6 @@ inline Promise<Unit> create_event_promise(EventFull ok, EventFull fail) { return Promise<Unit>(td::make_unique<detail::EventPromise>(std::move(ok), std::move(fail))); } -class SendClosure { - public: - template <class... ArgsT> - void operator()(ArgsT &&...args) const { - send_closure(std::forward<ArgsT>(args)...); - } -}; - -//template <class T> -//template <class... ArgsT> -//auto Promise<T>::send_closure(ArgsT &&... args) { -// return [promise = std::move(*this), t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&r_res) mutable { -// TRY_RESULT_PROMISE(promise, res, std::move(r_res)); -// td2::call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::move(res), std::move(promise)))); -// }; -//} - -template <class... ArgsT> -auto promise_send_closure(ArgsT &&...args) { - return [t = std::make_tuple(std::forward<ArgsT>(args)...)](auto &&res) mutable { - call_tuple(SendClosure(), std::tuple_cat(std::move(t), std::make_tuple(std::forward<decltype(res)>(res)))); - }; -} - -/*** FutureActor and PromiseActor ***/ template <class T> class FutureActor; @@ -618,57 +287,9 @@ FutureActor<T> send_promise(ActorId<ActorAT> actor_id, ResultT (ActorBT::*func)( return pf.move_future(); } -class PromiseCreator { - public: - template <class OkT, class ArgT = detail::drop_result_t<detail::get_arg_t<OkT>>> - static Promise<ArgT> lambda(OkT &&ok) { - return Promise<ArgT>(td::make_unique<detail::LambdaPromise<ArgT, std::decay_t<OkT>>>(std::forward<OkT>(ok))); - } - - template <class OkT, class ArgT = detail::drop_result_t<detail::get_arg_t<OkT>>> - static auto cancellable_lambda(CancellationToken cancellation_token, OkT &&ok) { - return Promise<ArgT>(td::make_unique<detail::CancellablePromise<detail::LambdaPromise<ArgT, std::decay_t<OkT>>>>( - std::move(cancellation_token), std::forward<OkT>(ok))); - } - - template <class... ArgsT> - static Promise<> join(ArgsT &&...args) { - return Promise<>(td::make_unique<detail::JoinPromise<ArgsT...>>(std::forward<ArgsT>(args)...)); - } - - template <class T> - static Promise<T> from_promise_actor(PromiseActor<T> &&from) { - return Promise<T>(td::make_unique<PromiseActor<T>>(std::move(from))); - } -}; - -inline void set_promises(vector<Promise<Unit>> &promises) { - auto moved_promises = std::move(promises); - promises.clear(); - - for (auto &promise : moved_promises) { - promise.set_value(Unit()); - } -} - template <class T> -void fail_promises(vector<Promise<T>> &promises, Status &&error) { - CHECK(error.is_error()); - auto moved_promises = std::move(promises); - promises.clear(); - - auto size = moved_promises.size(); - if (size == 0) { - return; - } - size--; - for (size_t i = 0; i < size; i++) { - auto &promise = moved_promises[i]; - if (promise) { - promise.set_error(error.clone()); - } - } - moved_promises[size].set_error(std::move(error)); +Promise<T> create_promise_from_promise_actor(PromiseActor<T> &&from) { + return Promise<T>(td::make_unique<PromiseActor<T>>(std::move(from))); } } // namespace td diff --git a/tdactor/td/actor/SleepActor.h b/tdactor/td/actor/SleepActor.h index 2c02db8af..8682ab0df 100644 --- a/tdactor/td/actor/SleepActor.h +++ b/tdactor/td/actor/SleepActor.h @@ -7,9 +7,9 @@ #pragma once #include "td/actor/actor.h" -#include "td/actor/PromiseFuture.h" #include "td/utils/common.h" +#include "td/utils/Promise.h" namespace td { diff --git a/tdactor/test/actors_simple.cpp b/tdactor/test/actors_simple.cpp index a76b80884..58f14ac48 100644 --- a/tdactor/test/actors_simple.cpp +++ b/tdactor/test/actors_simple.cpp @@ -16,6 +16,7 @@ #include "td/utils/Observer.h" #include "td/utils/port/FileFd.h" #include "td/utils/port/thread.h" +#include "td/utils/Promise.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" #include "td/utils/StringBuilder.h" |
