1 // 2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 // 7 #pragma once 8 9 #include "td/actor/actor.h" 10 #include "td/actor/PromiseFuture.h" 11 12 #include "td/utils/common.h" 13 #include "td/utils/Status.h" 14 15 namespace td { 16 17 class MultiPromiseInterface { 18 public: 19 virtual void add_promise(Promise<> &&promise) = 0; 20 virtual Promise<> get_promise() = 0; 21 22 virtual size_t promise_count() const = 0; 23 virtual void set_ignore_errors(bool ignore_errors) = 0; 24 25 MultiPromiseInterface() = default; 26 MultiPromiseInterface(const MultiPromiseInterface &) = delete; 27 MultiPromiseInterface &operator=(const MultiPromiseInterface &) = delete; 28 MultiPromiseInterface(MultiPromiseInterface &&) = default; 29 MultiPromiseInterface &operator=(MultiPromiseInterface &&) = default; 30 virtual ~MultiPromiseInterface() = default; 31 }; 32 33 class MultiPromise final : public MultiPromiseInterface { 34 public: add_promise(Promise<> && promise)35 void add_promise(Promise<> &&promise) final { 36 impl_->add_promise(std::move(promise)); 37 } get_promise()38 Promise<> get_promise() final { 39 return impl_->get_promise(); 40 } 41 promise_count()42 size_t promise_count() const final { 43 return impl_->promise_count(); 44 } set_ignore_errors(bool ignore_errors)45 void set_ignore_errors(bool ignore_errors) final { 46 impl_->set_ignore_errors(ignore_errors); 47 } 48 49 MultiPromise() = default; MultiPromise(unique_ptr<MultiPromiseInterface> impl)50 explicit MultiPromise(unique_ptr<MultiPromiseInterface> impl) : impl_(std::move(impl)) { 51 } 52 53 private: 54 unique_ptr<MultiPromiseInterface> impl_; 55 }; 56 57 class MultiPromiseActor final 58 : public Actor 59 , public MultiPromiseInterface { 60 public: MultiPromiseActor(string name)61 explicit MultiPromiseActor(string name) : name_(std::move(name)) { 62 } 63 64 void add_promise(Promise<Unit> &&promise) final; 65 66 Promise<Unit> get_promise() final; 67 68 void set_ignore_errors(bool ignore_errors) final; 69 70 size_t promise_count() const final; 71 72 private: 73 void set_result(Result<Unit> &&result); 74 75 string name_; 76 vector<Promise<Unit>> promises_; // promises waiting for result 77 vector<FutureActor<Unit>> futures_; // futures waiting for result of the queries 78 size_t received_results_ = 0; 79 bool ignore_errors_ = false; 80 Result<Unit> result_; 81 82 void raw_event(const Event::Raw &event) final; 83 84 void tear_down() final; 85 on_start_migrate(int32)86 void on_start_migrate(int32) final { 87 UNREACHABLE(); 88 } on_finish_migrate()89 void on_finish_migrate() final { 90 UNREACHABLE(); 91 } 92 }; 93 94 template <> 95 class ActorTraits<MultiPromiseActor> { 96 public: 97 static constexpr bool need_context = false; 98 static constexpr bool need_start_up = true; 99 }; 100 101 class MultiPromiseActorSafe final : public MultiPromiseInterface { 102 public: 103 void add_promise(Promise<Unit> &&promise) final; 104 Promise<Unit> get_promise() final; 105 void set_ignore_errors(bool ignore_errors) final; 106 size_t promise_count() const final; MultiPromiseActorSafe(string name)107 explicit MultiPromiseActorSafe(string name) : multi_promise_(td::make_unique<MultiPromiseActor>(std::move(name))) { 108 } 109 MultiPromiseActorSafe(const MultiPromiseActorSafe &other) = delete; 110 MultiPromiseActorSafe &operator=(const MultiPromiseActorSafe &other) = delete; 111 MultiPromiseActorSafe(MultiPromiseActorSafe &&other) = delete; 112 MultiPromiseActorSafe &operator=(MultiPromiseActorSafe &&other) = delete; 113 ~MultiPromiseActorSafe() final; 114 115 private: 116 unique_ptr<MultiPromiseActor> multi_promise_; 117 }; 118 119 } // namespace td 120