From b905a181618aeb686ce511052a55a9c40c4b0c5e Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 17 May 2021 16:19:02 +0400 Subject: [PATCH] Destroy all tgcalls instances before quit. --- Telegram/SourceFiles/calls/calls_instance.cpp | 34 ++++++++++++++++++- Telegram/SourceFiles/calls/calls_instance.h | 8 +++++ .../calls/group/calls_group_call.cpp | 13 +++++-- .../calls/group/calls_group_call.h | 2 ++ 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index be73872986..a3268fb8d2 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -73,6 +73,7 @@ public: void groupCallPlaySound(GroupCallSound sound) override; auto groupCallGetVideoCapture(const QString &deviceId) -> std::shared_ptr override; + FnMut groupCallAddAsyncWaiter() override; private: const not_null _instance; @@ -161,13 +162,24 @@ auto Instance::Delegate::groupCallGetVideoCapture(const QString &deviceId) return _instance->getVideoCapture(deviceId); } +FnMut Instance::Delegate::groupCallAddAsyncWaiter() { + return _instance->addAsyncWaiter(); +} + Instance::Instance() : _delegate(std::make_unique(this)) , _cachedDhConfig(std::make_unique()) , _chooseJoinAs(std::make_unique()) { } -Instance::~Instance() = default; +Instance::~Instance() { + destroyCurrentCall(); + + while (!_asyncWaiters.empty()) { + _asyncWaiters.front()->acquire(); + _asyncWaiters.erase(_asyncWaiters.begin()); + } +} void Instance::startOutgoingCall(not_null user, bool video) { if (activateCurrentCall()) { @@ -426,6 +438,26 @@ void Instance::setCurrentAudioDevice(bool input, const QString &deviceId) { } } +FnMut Instance::addAsyncWaiter() { + auto semaphore = std::make_unique(); + const auto raw = semaphore.get(); + const auto weak = base::make_weak(this); + _asyncWaiters.emplace(std::move(semaphore)); + return [raw, weak] { + raw->release(); + crl::on_main(weak, [raw, weak] { + auto &waiters = weak->_asyncWaiters; + auto wrapped = std::unique_ptr(raw); + const auto i = waiters.find(wrapped); + wrapped.release(); + + if (i != end(waiters)) { + waiters.erase(i); + } + }); + }; +} + bool Instance::isQuitPrevent() { if (!_currentCall || _currentCall->isIncomingWaiting()) { return false; diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index 8b9c3536f7..ff1f51c9ce 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mtproto/sender.h" +namespace crl { +class semaphore; +} // namespace crl + namespace Platform { enum class PermissionType; } // namespace Platform @@ -77,6 +81,8 @@ public: void setCurrentAudioDevice(bool input, const QString &deviceId); + [[nodiscard]] FnMut addAsyncWaiter(); + [[nodiscard]] bool isQuitPrevent(); private: @@ -132,6 +138,8 @@ private: const std::unique_ptr _chooseJoinAs; + base::flat_set> _asyncWaiters; + }; } // namespace Calls diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index a9ab69d1ce..78dc57830c 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -2504,9 +2504,14 @@ void GroupCall::destroyController() { if (_instance) { DEBUG_LOG(("Call Info: Destroying call controller..")); invalidate_weak_ptrs(&_instanceGuard); - crl::async([instance = base::take(_instance)]() mutable { + + crl::async([ + instance = base::take(_instance), + done = _delegate->groupCallAddAsyncWaiter() + ]() mutable { instance = nullptr; DEBUG_LOG(("Call Info: Call controller destroyed.")); + done(); }); } } @@ -2515,9 +2520,13 @@ void GroupCall::destroyScreencast() { if (_screenInstance) { DEBUG_LOG(("Call Info: Destroying call screen controller..")); invalidate_weak_ptrs(&_screenInstanceGuard); - crl::async([instance = base::take(_screenInstance)]() mutable { + crl::async([ + instance = base::take(_screenInstance), + done = _delegate->groupCallAddAsyncWaiter() + ]() mutable { instance = nullptr; DEBUG_LOG(("Call Info: Call screen controller destroyed.")); + done(); }); } } diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 55f6a29662..b5f6683a16 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -167,6 +167,8 @@ public: virtual void groupCallPlaySound(GroupCallSound sound) = 0; virtual auto groupCallGetVideoCapture(const QString &deviceId) -> std::shared_ptr = 0; + + [[nodiscard]] virtual FnMut groupCallAddAsyncWaiter() = 0; }; using GlobalShortcutManager = base::GlobalShortcutManager;