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/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<ProcessState> 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<QEvent>(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<ProcessorEvent*>(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

View File

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

View File

@ -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);
}

View File

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

View File

@ -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() {

View File

@ -29,6 +29,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <mach-o/dyld.h>
#include <AVFoundation/AVFoundation.h>
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]);

View File

@ -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();

View File

@ -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();