diff --git a/Telegram/SourceFiles/core/main_queue_processor.cpp b/Telegram/SourceFiles/core/main_queue_processor.cpp index 73e43064ab..9eb07a2361 100644 --- a/Telegram/SourceFiles/core/main_queue_processor.cpp +++ b/Telegram/SourceFiles/core/main_queue_processor.cpp @@ -8,73 +8,101 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "core/main_queue_processor.h" #include "core/sandbox.h" +#include "platform/platform_specific.h" namespace Core { namespace { -QMutex ProcessorMutex; -MainQueueProcessor *ProcessorInstance/* = nullptr*/; - constexpr auto kProcessorEvent = QEvent::Type(QEvent::User + 1); static_assert(kProcessorEvent < QEvent::MaxUser); -class ProcessorEvent : public QEvent { -public: - ProcessorEvent(void (*callable)(void*), void *argument); - - void process(); - -private: - void (*_callable)(void*) = nullptr; - void *_argument = nullptr; +QMutex ProcessorMutex; +MainQueueProcessor *ProcessorInstance/* = nullptr*/; +enum class ProcessState : int { + Processed, + FillingUp, + Waiting, }; -ProcessorEvent::ProcessorEvent(void (*callable)(void*), void *argument) -: QEvent(kProcessorEvent) -, _callable(callable) -, _argument(argument) { +std::atomic MainQueueProcessState/* = ProcessState(0)*/; +void (*MainQueueProcessCallback)(void*)/* = nullptr*/; +void *MainQueueProcessArgument/* = nullptr*/; + +void PushToMainQueueGeneric(void (*callable)(void*), void *argument) { + Expects(Platform::UseMainQueueGeneric()); + + auto expected = ProcessState::Processed; + const auto fill = MainQueueProcessState.compare_exchange_strong( + expected, + ProcessState::FillingUp); + if (fill) { + MainQueueProcessCallback = callable; + MainQueueProcessArgument = argument; + MainQueueProcessState.store(ProcessState::Waiting); + } + + auto event = std::make_unique(kProcessorEvent); + + QMutexLocker lock(&ProcessorMutex); + if (ProcessorInstance) { + QApplication::postEvent(ProcessorInstance, event.release()); + } } -void ProcessorEvent::process() { - _callable(_argument); -} +void DrainMainQueueGeneric() { + Expects(Platform::UseMainQueueGeneric()); -void ProcessObservables() { - Global::RefHandleObservables().call(); + if (MainQueueProcessState.load() != ProcessState::Waiting) { + return; + } + const auto callback = MainQueueProcessCallback; + const auto argument = MainQueueProcessArgument; + MainQueueProcessState.store(ProcessState::Processed); + + callback(argument); } } // namespace MainQueueProcessor::MainQueueProcessor() { - acquire(); - - crl::init_main_queue([](void (*callable)(void*), void *argument) { - QMutexLocker lock(&ProcessorMutex); - - if (ProcessorInstance) { - const auto event = new ProcessorEvent(callable, argument); - QApplication::postEvent(ProcessorInstance, event); - } - }); - crl::wrap_main_queue([](void (*callable)(void*), void *argument) { - Sandbox::Instance().customEnterFromEventLoop([&] { - callable(argument); + if constexpr (Platform::UseMainQueueGeneric()) { + acquire(); + crl::init_main_queue(PushToMainQueueGeneric); + } else { + crl::wrap_main_queue([](void (*callable)(void*), void *argument) { + Sandbox::Instance().customEnterFromEventLoop([&] { + callable(argument); + }); }); - }); + } - base::InitObservables(ProcessObservables); + Core::Sandbox::Instance().widgetUpdateRequests( + ) | rpl::start_with_next([] { + if constexpr (Platform::UseMainQueueGeneric()) { + DrainMainQueueGeneric(); + } else { + Platform::DrainMainQueue(); + } + }, _lifetime); + + base::InitObservables([] { + Global::RefHandleObservables().call(); + }); } bool MainQueueProcessor::event(QEvent *event) { - if (event->type() == kProcessorEvent) { - static_cast(event)->process(); - return true; + if constexpr (Platform::UseMainQueueGeneric()) { + if (event->type() == kProcessorEvent) { + DrainMainQueueGeneric(); + return true; + } } return QObject::event(event); } void MainQueueProcessor::acquire() { + Expects(Platform::UseMainQueueGeneric()); Expects(ProcessorInstance == nullptr); QMutexLocker lock(&ProcessorMutex); @@ -82,6 +110,7 @@ void MainQueueProcessor::acquire() { } void MainQueueProcessor::release() { + Expects(Platform::UseMainQueueGeneric()); Expects(ProcessorInstance == this); QMutexLocker lock(&ProcessorMutex); @@ -89,7 +118,9 @@ void MainQueueProcessor::release() { } MainQueueProcessor::~MainQueueProcessor() { - release(); + if constexpr (Platform::UseMainQueueGeneric()) { + release(); + } } } // namespace diff --git a/Telegram/SourceFiles/core/main_queue_processor.h b/Telegram/SourceFiles/core/main_queue_processor.h index 3e8b1567f4..686801e1e0 100644 --- a/Telegram/SourceFiles/core/main_queue_processor.h +++ b/Telegram/SourceFiles/core/main_queue_processor.h @@ -21,6 +21,8 @@ private: void acquire(); void release(); + rpl::lifetime _lifetime; + }; } // namespace Core diff --git a/Telegram/SourceFiles/core/sandbox.cpp b/Telegram/SourceFiles/core/sandbox.cpp index c02a282637..01cd5c79a9 100644 --- a/Telegram/SourceFiles/core/sandbox.cpp +++ b/Telegram/SourceFiles/core/sandbox.cpp @@ -503,14 +503,6 @@ bool Sandbox::notify(QObject *receiver, QEvent *e) { const auto type = e->type(); if (type == QEvent::UpdateRequest) { _widgetUpdateRequests.fire({}); - // Profiling. - //const auto time = crl::now(); - //LOG(("[%1] UPDATE STARTED").arg(time)); - //const auto guard = gsl::finally([&] { - // const auto now = crl::now(); - // LOG(("[%1] UPDATE FINISHED (%2)").arg(now).arg(now - time)); - //}); - //return QApplication::notify(receiver, e); } return QApplication::notify(receiver, e); } diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h index 5bb6a1a0da..14485149e5 100644 --- a/Telegram/SourceFiles/platform/linux/specific_linux.h +++ b/Telegram/SourceFiles/platform/linux/specific_linux.h @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "platform/platform_specific.h" + #include #include @@ -39,6 +41,10 @@ inline std::optional LastUserInputTime() { return std::nullopt; } +inline constexpr bool UseMainQueueGeneric() { + return true; +} + } // namespace Platform inline QString psServerPrefix() { diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h index ee354e43ba..a5bdf52098 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.h +++ b/Telegram/SourceFiles/platform/mac/specific_mac.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "platform/platform_specific.h" #include "platform/mac/specific_mac_p.h" namespace Data { @@ -23,6 +24,10 @@ QString CurrentExecutablePath(int argc, char *argv[]); void RemoveQuarantine(const QString &path); +inline constexpr bool UseMainQueueGeneric() { + return false; +} + namespace ThirdParty { inline void start() { diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm index 500e2f89eb..0c883144de 100644 --- a/Telegram/SourceFiles/platform/mac/specific_mac.mm +++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm @@ -29,6 +29,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include +extern "C" { +void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg); +} // extern "C" + namespace { QStringList _initLogs; @@ -139,6 +143,10 @@ void RemoveQuarantine(const QString &path) { removexattr(local.data(), kQuarantineAttribute, 0); } +void DrainMainQueue() { + _dispatch_main_queue_callback_4CF(nullptr); +} + void RegisterCustomScheme() { #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); diff --git a/Telegram/SourceFiles/platform/platform_specific.h b/Telegram/SourceFiles/platform/platform_specific.h index 5700cc9746..330ba48d39 100644 --- a/Telegram/SourceFiles/platform/platform_specific.h +++ b/Telegram/SourceFiles/platform/platform_specific.h @@ -45,6 +45,9 @@ bool OpenSystemSettings(SystemSettingsType type); return LastUserInputTime().has_value(); } +[[nodiscard]] constexpr bool UseMainQueueGeneric(); +void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false. + namespace ThirdParty { void start(); diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h index 0360028132..5f6995fd58 100644 --- a/Telegram/SourceFiles/platform/win/specific_win.h +++ b/Telegram/SourceFiles/platform/win/specific_win.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "platform/platform_specific.h" #include "platform/win/wrapper_windows_h.h" namespace Data { @@ -38,6 +39,10 @@ inline void ReInitOnTopPanel(QWidget *panel) { QString CurrentExecutablePath(int argc, char *argv[]); +inline constexpr bool UseMainQueueGeneric() { + return true; +} + namespace ThirdParty { void start();