Hook main queue processing to update requests.

This commit is contained in:
John Preston 2019-07-04 15:33:11 +02:00
parent b1807938ad
commit 0e964b06dc
8 changed files with 100 additions and 48 deletions

View File

@ -8,73 +8,101 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/main_queue_processor.h" #include "core/main_queue_processor.h"
#include "core/sandbox.h" #include "core/sandbox.h"
#include "platform/platform_specific.h"
namespace Core { namespace Core {
namespace { namespace {
QMutex ProcessorMutex;
MainQueueProcessor *ProcessorInstance/* = nullptr*/;
constexpr auto kProcessorEvent = QEvent::Type(QEvent::User + 1); constexpr auto kProcessorEvent = QEvent::Type(QEvent::User + 1);
static_assert(kProcessorEvent < QEvent::MaxUser); static_assert(kProcessorEvent < QEvent::MaxUser);
class ProcessorEvent : public QEvent { QMutex ProcessorMutex;
public: MainQueueProcessor *ProcessorInstance/* = nullptr*/;
ProcessorEvent(void (*callable)(void*), void *argument);
void process();
private:
void (*_callable)(void*) = nullptr;
void *_argument = nullptr;
enum class ProcessState : int {
Processed,
FillingUp,
Waiting,
}; };
ProcessorEvent::ProcessorEvent(void (*callable)(void*), void *argument) std::atomic<ProcessState> MainQueueProcessState/* = ProcessState(0)*/;
: QEvent(kProcessorEvent) void (*MainQueueProcessCallback)(void*)/* = nullptr*/;
, _callable(callable) void *MainQueueProcessArgument/* = nullptr*/;
, _argument(argument) {
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<QEvent>(kProcessorEvent);
QMutexLocker lock(&ProcessorMutex);
if (ProcessorInstance) {
QApplication::postEvent(ProcessorInstance, event.release());
}
} }
void ProcessorEvent::process() { void DrainMainQueueGeneric() {
_callable(_argument); Expects(Platform::UseMainQueueGeneric());
}
void ProcessObservables() { if (MainQueueProcessState.load() != ProcessState::Waiting) {
Global::RefHandleObservables().call(); return;
}
const auto callback = MainQueueProcessCallback;
const auto argument = MainQueueProcessArgument;
MainQueueProcessState.store(ProcessState::Processed);
callback(argument);
} }
} // namespace } // namespace
MainQueueProcessor::MainQueueProcessor() { MainQueueProcessor::MainQueueProcessor() {
acquire(); if constexpr (Platform::UseMainQueueGeneric()) {
acquire();
crl::init_main_queue([](void (*callable)(void*), void *argument) { crl::init_main_queue(PushToMainQueueGeneric);
QMutexLocker lock(&ProcessorMutex); } else {
crl::wrap_main_queue([](void (*callable)(void*), void *argument) {
if (ProcessorInstance) { Sandbox::Instance().customEnterFromEventLoop([&] {
const auto event = new ProcessorEvent(callable, argument); callable(argument);
QApplication::postEvent(ProcessorInstance, event); });
}
});
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) { bool MainQueueProcessor::event(QEvent *event) {
if (event->type() == kProcessorEvent) { if constexpr (Platform::UseMainQueueGeneric()) {
static_cast<ProcessorEvent*>(event)->process(); if (event->type() == kProcessorEvent) {
return true; DrainMainQueueGeneric();
return true;
}
} }
return QObject::event(event); return QObject::event(event);
} }
void MainQueueProcessor::acquire() { void MainQueueProcessor::acquire() {
Expects(Platform::UseMainQueueGeneric());
Expects(ProcessorInstance == nullptr); Expects(ProcessorInstance == nullptr);
QMutexLocker lock(&ProcessorMutex); QMutexLocker lock(&ProcessorMutex);
@ -82,6 +110,7 @@ void MainQueueProcessor::acquire() {
} }
void MainQueueProcessor::release() { void MainQueueProcessor::release() {
Expects(Platform::UseMainQueueGeneric());
Expects(ProcessorInstance == this); Expects(ProcessorInstance == this);
QMutexLocker lock(&ProcessorMutex); QMutexLocker lock(&ProcessorMutex);
@ -89,7 +118,9 @@ void MainQueueProcessor::release() {
} }
MainQueueProcessor::~MainQueueProcessor() { MainQueueProcessor::~MainQueueProcessor() {
release(); if constexpr (Platform::UseMainQueueGeneric()) {
release();
}
} }
} // namespace } // namespace

View File

@ -21,6 +21,8 @@ private:
void acquire(); void acquire();
void release(); void release();
rpl::lifetime _lifetime;
}; };
} // namespace Core } // namespace Core

View File

@ -503,14 +503,6 @@ bool Sandbox::notify(QObject *receiver, QEvent *e) {
const auto type = e->type(); const auto type = e->type();
if (type == QEvent::UpdateRequest) { if (type == QEvent::UpdateRequest) {
_widgetUpdateRequests.fire({}); _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); return QApplication::notify(receiver, e);
} }

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "platform/platform_specific.h"
#include <execinfo.h> #include <execinfo.h>
#include <signal.h> #include <signal.h>
@ -39,6 +41,10 @@ inline std::optional<crl::time> LastUserInputTime() {
return std::nullopt; return std::nullopt;
} }
inline constexpr bool UseMainQueueGeneric() {
return true;
}
} // namespace Platform } // namespace Platform
inline QString psServerPrefix() { inline QString psServerPrefix() {

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "platform/platform_specific.h"
#include "platform/mac/specific_mac_p.h" #include "platform/mac/specific_mac_p.h"
namespace Data { namespace Data {
@ -23,6 +24,10 @@ QString CurrentExecutablePath(int argc, char *argv[]);
void RemoveQuarantine(const QString &path); void RemoveQuarantine(const QString &path);
inline constexpr bool UseMainQueueGeneric() {
return false;
}
namespace ThirdParty { namespace ThirdParty {
inline void start() { inline void start() {

View File

@ -29,6 +29,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <mach-o/dyld.h> #include <mach-o/dyld.h>
#include <AVFoundation/AVFoundation.h> #include <AVFoundation/AVFoundation.h>
extern "C" {
void _dispatch_main_queue_callback_4CF(mach_msg_header_t *msg);
} // extern "C"
namespace { namespace {
QStringList _initLogs; QStringList _initLogs;
@ -139,6 +143,10 @@ void RemoveQuarantine(const QString &path) {
removexattr(local.data(), kQuarantineAttribute, 0); removexattr(local.data(), kQuarantineAttribute, 0);
} }
void DrainMainQueue() {
_dispatch_main_queue_callback_4CF(nullptr);
}
void RegisterCustomScheme() { void RegisterCustomScheme() {
#ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME #ifndef TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); OSStatus result = LSSetDefaultHandlerForURLScheme(CFSTR("tg"), (CFStringRef)[[NSBundle mainBundle] bundleIdentifier]);

View File

@ -45,6 +45,9 @@ bool OpenSystemSettings(SystemSettingsType type);
return LastUserInputTime().has_value(); return LastUserInputTime().has_value();
} }
[[nodiscard]] constexpr bool UseMainQueueGeneric();
void DrainMainQueue(); // Needed only if UseMainQueueGeneric() is false.
namespace ThirdParty { namespace ThirdParty {
void start(); void start();

View File

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "platform/platform_specific.h"
#include "platform/win/wrapper_windows_h.h" #include "platform/win/wrapper_windows_h.h"
namespace Data { namespace Data {
@ -38,6 +39,10 @@ inline void ReInitOnTopPanel(QWidget *panel) {
QString CurrentExecutablePath(int argc, char *argv[]); QString CurrentExecutablePath(int argc, char *argv[]);
inline constexpr bool UseMainQueueGeneric() {
return true;
}
namespace ThirdParty { namespace ThirdParty {
void start(); void start();