diff --git a/td/telegram/AlarmManager.cpp b/td/telegram/AlarmManager.cpp index f0cccd898..3dbff646b 100644 --- a/td/telegram/AlarmManager.cpp +++ b/td/telegram/AlarmManager.cpp @@ -6,13 +6,51 @@ // #include "td/telegram/AlarmManager.h" +#include "td/telegram/Global.h" + namespace td { AlarmManager::AlarmManager(ActorShared<> parent) : parent_(std::move(parent)) { + alarm_timeout_.set_callback(on_alarm_timeout_callback); + alarm_timeout_.set_callback_data(static_cast(this)); } void AlarmManager::tear_down() { + while (!pending_alarms_.empty()) { + auto it = pending_alarms_.begin(); + auto alarm_id = it->first; + auto promise = std::move(it->second); + pending_alarms_.erase(it); + promise.set_error(G()->request_aborted_error()); + alarm_timeout_.cancel_timeout(alarm_id); + } parent_.reset(); } +void AlarmManager::on_alarm_timeout_callback(void *alarm_manager_ptr, int64 alarm_id) { + auto alarm_manager = static_cast(alarm_manager_ptr); + auto alarm_manager_id = alarm_manager->actor_id(alarm_manager); + send_closure_later(alarm_manager_id, &AlarmManager::on_alarm_timeout, alarm_id); +} + +void AlarmManager::on_alarm_timeout(int64 alarm_id) { + auto it = pending_alarms_.find(alarm_id); + if (it == pending_alarms_.end()) { + return; + } + auto promise = std::move(it->second); + pending_alarms_.erase(alarm_id); + promise.set_value(Unit()); +} + +void AlarmManager::set_alarm(double seconds, Promise &&promise) { + if (seconds < 0 || seconds > 3e9) { + return promise.set_error(Status::Error(400, "Wrong parameter seconds specified")); + } + + auto alarm_id = alarm_id_++; + pending_alarms_.emplace(alarm_id, std::move(promise)); + alarm_timeout_.set_timeout_in(alarm_id, seconds); +} + } // namespace td diff --git a/td/telegram/AlarmManager.h b/td/telegram/AlarmManager.h index b4e65cca3..d58091935 100644 --- a/td/telegram/AlarmManager.h +++ b/td/telegram/AlarmManager.h @@ -7,8 +7,11 @@ #pragma once #include "td/actor/actor.h" +#include "td/actor/MultiTimeout.h" #include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" +#include "td/utils/Promise.h" namespace td { @@ -18,10 +21,20 @@ class AlarmManager final : public Actor { public: explicit AlarmManager(ActorShared<> parent); + void set_alarm(double seconds, Promise &&promise); + private: void tear_down() final; + static void on_alarm_timeout_callback(void *alarm_manager_ptr, int64 alarm_id); + + void on_alarm_timeout(int64 alarm_id); + ActorShared<> parent_; + + int64 alarm_id_ = 1; + FlatHashMap> pending_alarms_; + MultiTimeout alarm_timeout_{"AlarmTimeout"}; }; } // namespace td diff --git a/td/telegram/Requests.cpp b/td/telegram/Requests.cpp index 054ab8f65..510715521 100644 --- a/td/telegram/Requests.cpp +++ b/td/telegram/Requests.cpp @@ -8,6 +8,7 @@ #include "td/telegram/AccentColorId.h" #include "td/telegram/AccountManager.h" +#include "td/telegram/AlarmManager.h" #include "td/telegram/AnimationsManager.h" #include "td/telegram/Application.h" #include "td/telegram/AttachMenuManager.h" @@ -7704,14 +7705,8 @@ void Requests::on_request(uint64 id, td_api::answerCustomQuery &request) { } void Requests::on_request(uint64 id, const td_api::setAlarm &request) { - if (request.seconds_ < 0 || request.seconds_ > 3e9) { - return send_error_raw(id, 400, "Wrong parameter seconds specified"); - } - - // TODO - int64 alarm_id = td_->alarm_id_++; - td_->pending_alarms_.emplace(alarm_id, id); - td_->alarm_timeout_.set_timeout_in(alarm_id, request.seconds_); + CREATE_OK_REQUEST_PROMISE(); + send_closure(td_->alarm_manager_, &AlarmManager::set_alarm, request.seconds_, std::move(promise)); } void Requests::on_request(uint64 id, td_api::searchHashtags &request) { diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 419083c11..b3b993116 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -135,25 +135,6 @@ Td::Td(unique_ptr callback, Options options) Td::~Td() = default; -void Td::on_alarm_timeout_callback(void *td_ptr, int64 alarm_id) { - auto td = static_cast(td_ptr); - auto td_id = td->actor_id(td); - send_closure_later(td_id, &Td::on_alarm_timeout, alarm_id); -} - -void Td::on_alarm_timeout(int64 alarm_id) { - if (close_flag_ >= 2) { - // pending_alarms_ was already cleared - return; - } - - auto it = pending_alarms_.find(alarm_id); - CHECK(it != pending_alarms_.end()); - uint64 request_id = it->second; - pending_alarms_.erase(alarm_id); - send_result(request_id, make_tl_object()); -} - bool Td::ignore_background_updates() const { return can_ignore_background_updates_ && option_manager_->get_option_boolean("ignore_background_updates"); } @@ -456,9 +437,6 @@ void Td::start_up() { alarm_manager_ = create_actor("AlarmManager", create_reference()); - alarm_timeout_.set_callback(on_alarm_timeout_callback); - alarm_timeout_.set_callback_data(static_cast(this)); - CHECK(state_ == State::WaitParameters); for (auto &update : get_fake_current_state()) { send_update(std::move(update)); @@ -624,12 +602,6 @@ void Td::dec_request_actor_refcnt() { } void Td::clear_requests() { - while (!pending_alarms_.empty()) { - auto it = pending_alarms_.begin(); - auto alarm_id = it->first; - pending_alarms_.erase(it); - alarm_timeout_.cancel_timeout(alarm_id); - } while (!request_set_.empty()) { uint64 id = request_set_.begin()->first; if (destroy_flag_) { @@ -774,6 +746,7 @@ void Td::close_impl(bool destroy_flag) { close_flag_ = 4; G()->set_close_flag(); clear_requests(); + alarm_manager_.reset(); send_update(td_api::make_object( td_api::make_object())); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 80da879af..27374be2a 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -16,7 +16,6 @@ #include "td/telegram/telegram_api.h" #include "td/actor/actor.h" -#include "td/actor/MultiTimeout.h" #include "td/utils/buffer.h" #include "td/utils/common.h" @@ -375,10 +374,6 @@ class Td final : public Actor { bool can_ignore_background_updates_ = false; - int64 alarm_id_ = 1; - FlatHashMap pending_alarms_; - MultiTimeout alarm_timeout_{"AlarmTimeout"}; - vector>> pending_preauthentication_requests_; vector>> pending_set_parameters_requests_; @@ -392,10 +387,6 @@ class Td final : public Actor { vector> get_fake_current_state() const; - static void on_alarm_timeout_callback(void *td_ptr, int64 alarm_id); - - void on_alarm_timeout(int64 alarm_id); - template friend class RequestActor; // uses send_result/send_error friend class AuthManager; // uses send_result/send_error, TODO pass Promise<>