Replace base/task_queue with crl.

This commit is contained in:
John Preston 2017-12-31 00:28:38 +03:00
parent ae7e5be5cd
commit af552fb4c0
21 changed files with 135 additions and 604 deletions

View File

@ -1,393 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "base/task_queue.h"
#include <thread>
#include <condition_variable>
namespace base {
namespace {
auto MainThreadId = std::this_thread::get_id();
const auto MaxThreadsCount = qMax(std::thread::hardware_concurrency(), 2U);
} // namespace
class TaskQueue::TaskQueueList {
public:
TaskQueueList();
void Register(TaskQueue *queue);
void Unregister(TaskQueue *queue);
bool IsInList(TaskQueue *queue) const;
void Clear();
bool Empty(int list_index_) const;
TaskQueue *TakeFirst(int list_index_);
private:
void Insert(TaskQueue *queue, int list_index_);
void Remove(TaskQueue *queue, int list_index_);
TaskQueue *Tail() { return &tail_; }
const TaskQueue *Tail() const { return &tail_; }
TaskQueue tail_ = { Type::Special, Priority::Normal };
TaskQueue *(lists_[kQueuesListsCount]);
};
class TaskQueue::TaskThreadPool {
struct Private {
};
public:
TaskThreadPool(const Private &) { }
static const std::shared_ptr<TaskThreadPool> &Instance();
void AddQueueTask(TaskQueue *queue, Task &&task);
void RemoveQueue(TaskQueue *queue);
~TaskThreadPool();
private:
void ThreadFunction();
std::vector<std::thread> threads_;
QMutex queues_mutex_;
// queues_mutex_ must be locked when working with the list.
TaskQueueList queue_list_;
QWaitCondition thread_condition_;
bool stopped_ = false;
int tasks_in_process_ = 0;
int background_tasks_in_process_ = 0;
};
TaskQueue::TaskQueueList::TaskQueueList() {
for (auto &list : lists_) {
list = &tail_;
}
}
void TaskQueue::TaskQueueList::Register(TaskQueue *queue) {
Assert(!queue->SerialTaskInProcess());
Insert(queue, kAllQueuesList);
if (queue->priority_ == Priority::Normal) {
Insert(queue, kOnlyNormalQueuesList);
}
}
void TaskQueue::TaskQueueList::Unregister(TaskQueue *queue) {
Remove(queue, kAllQueuesList);
if (queue->priority_ == Priority::Normal) {
Remove(queue, kOnlyNormalQueuesList);
}
}
void TaskQueue::TaskQueueList::Insert(TaskQueue *queue, int list_index_) {
Assert(list_index_ < kQueuesListsCount);
auto tail = Tail();
if (lists_[list_index_] == tail) {
lists_[list_index_] = queue;
}
auto &list_entry = queue->list_entries_[list_index_];
Assert(list_entry.after == nullptr);
if ((list_entry.before = tail->list_entries_[list_index_].before)) {
list_entry.before->list_entries_[list_index_].after = queue;
}
list_entry.after = tail;
tail->list_entries_[list_index_].before = queue;
}
void TaskQueue::TaskQueueList::Remove(TaskQueue *queue, int list_index_) {
Assert(list_index_ < kQueuesListsCount);
auto &list_entry = queue->list_entries_[list_index_];
Assert(list_entry.after != nullptr);
if (lists_[list_index_] == queue) {
lists_[list_index_] = list_entry.after;
} else {
Assert(list_entry.before != nullptr);
list_entry.before->list_entries_[list_index_].after = list_entry.after;
}
list_entry.after->list_entries_[list_index_].before = list_entry.before;
list_entry.before = list_entry.after = nullptr;
}
bool TaskQueue::TaskQueueList::IsInList(TaskQueue *queue) const {
if (queue->list_entries_[kAllQueuesList].after) {
return true;
}
Assert(queue->list_entries_[kOnlyNormalQueuesList].after == nullptr);
return false;
}
void TaskQueue::TaskQueueList::Clear() {
auto tail = Tail();
for (int i = 0; i < kQueuesListsCount; ++i) {
for (auto j = lists_[i], next = j; j != tail; j = next) {
auto &list_entry = j->list_entries_[i];
next = list_entry.after;
list_entry.before = list_entry.after = nullptr;
}
lists_[i] = tail;
}
}
bool TaskQueue::TaskQueueList::Empty(int list_index_) const {
Assert(list_index_ < kQueuesListsCount);
auto list = lists_[list_index_];
Assert(list != nullptr);
return (list->list_entries_[list_index_].after == nullptr);
}
TaskQueue *TaskQueue::TaskQueueList::TakeFirst(int list_index_) {
Assert(!Empty(list_index_));
auto queue = lists_[list_index_];
Unregister(queue);
// log_msgs.push_back("Unregistered from list in TakeFirst");
return queue;
}
void TaskQueue::TaskThreadPool::AddQueueTask(TaskQueue *queue, Task &&task) {
QMutexLocker lock(&queues_mutex_);
queue->tasks_.push_back(std::move(task));
auto list_was_empty = queue_list_.Empty(kAllQueuesList);
auto threads_count = threads_.size();
auto all_threads_processing = (threads_count == tasks_in_process_);
auto some_threads_are_vacant = !all_threads_processing && list_was_empty;
auto will_create_thread = !some_threads_are_vacant && (threads_count < MaxThreadsCount);
if (!queue->SerialTaskInProcess()) {
if (!queue_list_.IsInList(queue)) {
queue_list_.Register(queue);
}
}
if (will_create_thread) {
threads_.emplace_back([this]() {
ThreadFunction();
});
} else if (some_threads_are_vacant) {
Assert(threads_count > tasks_in_process_);
thread_condition_.wakeOne();
}
}
void TaskQueue::TaskThreadPool::RemoveQueue(TaskQueue *queue) {
QMutexLocker lock(&queues_mutex_);
if (queue_list_.IsInList(queue)) {
queue_list_.Unregister(queue);
}
if (queue->destroyed_flag_) {
*queue->destroyed_flag_ = true;
}
}
TaskQueue::TaskThreadPool::~TaskThreadPool() {
{
QMutexLocker lock(&queues_mutex_);
queue_list_.Clear();
stopped_ = true;
}
thread_condition_.wakeAll();
for (auto &thread : threads_) {
thread.join();
}
}
const std::shared_ptr<TaskQueue::TaskThreadPool> &TaskQueue::TaskThreadPool::Instance() { // static
static auto Pool = std::make_shared<TaskThreadPool>(Private());
return Pool;
}
void TaskQueue::TaskThreadPool::ThreadFunction() {
// Flag marking that the previous processed task was
// with a Background priority. We count all the background
// tasks being processed.
bool background_task = false;
// Saved serial queue pointer. When we process a serial
// queue task we don't return the queue to the list until
// the task is processed and we return it on the next cycle.
TaskQueue *serial_queue = nullptr;
bool serial_queue_destroyed = false;
bool task_was_processed = false;
while (true) {
Task task;
{
QMutexLocker lock(&queues_mutex_);
// Finish the previous task processing.
if (task_was_processed) {
--tasks_in_process_;
}
if (background_task) {
--background_tasks_in_process_;
background_task = false;
}
if (serial_queue) {
if (!serial_queue_destroyed) {
serial_queue->destroyed_flag_ = nullptr;
if (!serial_queue->tasks_.empty()) {
queue_list_.Register(serial_queue);
}
}
serial_queue = nullptr;
serial_queue_destroyed = false;
}
// Wait for a task to appear in the queues list.
while (queue_list_.Empty(kAllQueuesList)) {
if (stopped_) {
return;
}
thread_condition_.wait(&queues_mutex_);
}
// Select a task we will be processing.
auto processing_background = (background_tasks_in_process_ > 0);
auto take_only_normal = processing_background && !queue_list_.Empty(kOnlyNormalQueuesList);
auto take_from_list_ = take_only_normal ? kOnlyNormalQueuesList : kAllQueuesList;
auto queue = queue_list_.TakeFirst(take_from_list_);
Assert(!queue->tasks_.empty());
task = std::move(queue->tasks_.front());
queue->tasks_.pop_front();
if (queue->type_ == Type::Serial) {
// Serial queues are returned in the list for processing
// only after the task is finished.
serial_queue = queue;
Assert(serial_queue->destroyed_flag_ == nullptr);
serial_queue->destroyed_flag_ = &serial_queue_destroyed;
} else if (!queue->tasks_.empty()) {
queue_list_.Register(queue);
}
++tasks_in_process_;
task_was_processed = true;
if (queue->priority_ == Priority::Background) {
++background_tasks_in_process_;
background_task = true;
}
}
task();
}
}
TaskQueue::TaskQueue(Type type, Priority priority)
: type_(type)
, priority_(priority) {
if (type_ != Type::Main && type_ != Type::Special) {
weak_thread_pool_ = TaskThreadPool::Instance();
}
}
TaskQueue::~TaskQueue() {
if (type_ != Type::Main && type_ != Type::Special) {
if (auto thread_pool = weak_thread_pool_.lock()) {
thread_pool->RemoveQueue(this);
}
}
}
void TaskQueue::Put(Task &&task) {
if (type_ == Type::Main) {
QMutexLocker lock(&tasks_mutex_);
tasks_.push_back(std::move(task));
Sandbox::MainThreadTaskAdded();
} else {
Assert(type_ != Type::Special);
TaskThreadPool::Instance()->AddQueueTask(this, std::move(task));
}
}
void TaskQueue::ProcessMainTasks() { // static
Assert(std::this_thread::get_id() == MainThreadId);
while (ProcessOneMainTask()) {
}
}
void TaskQueue::ProcessMainTasks(TimeMs max_time_spent) { // static
Assert(std::this_thread::get_id() == MainThreadId);
auto start_time = getms();
while (ProcessOneMainTask()) {
if (getms() >= start_time + max_time_spent) {
break;
}
}
}
bool TaskQueue::ProcessOneMainTask() { // static
Task task;
{
QMutexLocker lock(&Main().tasks_mutex_);
auto &tasks = Main().tasks_;
if (tasks.empty()) {
return false;
}
task = std::move(tasks.front());
tasks.pop_front();
}
task();
return true;
}
bool TaskQueue::IsMyThread() const {
if (type_ == Type::Main) {
return (std::this_thread::get_id() == MainThreadId);
}
Assert(type_ != Type::Special);
return false;
}
// Default queues.
TaskQueue &TaskQueue::Main() { // static
static TaskQueue MainQueue { Type::Main, Priority::Normal };
return MainQueue;
}
TaskQueue &TaskQueue::Normal() { // static
static TaskQueue NormalQueue { Type::Concurrent, Priority::Normal };
return NormalQueue;
}
TaskQueue &TaskQueue::Background() { // static
static TaskQueue BackgroundQueue { Type::Concurrent, Priority::Background };
return BackgroundQueue;
}
} // namespace base

View File

@ -1,102 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop version of Telegram messaging app, see https://telegram.org
Telegram Desktop is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
It is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
In addition, as a special exception, the copyright holders give permission
to link the code of portions of this program with the OpenSSL library.
Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#pragma once
#include <memory>
namespace base {
using Task = lambda_once<void()>;
// An attempt to create/use a TaskQueue or one of the default queues
// after the main() has returned leads to an undefined behaviour.
class TaskQueue {
enum class Type {
Main, // Unique queue for main thread tasks.
Serial,
Concurrent,
Special, // Unique special queue for thread pool lists terminal item.
};
public:
enum class Priority {
Normal,
Background,
};
// Creating custom serial queues.
TaskQueue(Priority priority) : TaskQueue(Type::Serial, priority) {
}
// Default main and two concurrent queues.
static TaskQueue &Main();
static TaskQueue &Normal();
static TaskQueue &Background();
void Put(Task &&task);
static void ProcessMainTasks();
static void ProcessMainTasks(TimeMs max_time_spent);
~TaskQueue();
private:
static bool ProcessOneMainTask();
TaskQueue(Type type, Priority priority);
bool IsMyThread() const;
bool SerialTaskInProcess() const {
return (destroyed_flag_ != nullptr);
}
const Type type_;
const Priority priority_;
std::deque<Task> tasks_;
QMutex tasks_mutex_; // Only for the main queue.
// Only for the other queues, not main.
class TaskThreadPool;
std::weak_ptr<TaskThreadPool> weak_thread_pool_;
class TaskQueueList;
struct TaskQueueListEntry {
TaskQueue *before = nullptr;
TaskQueue *after = nullptr;
};
// Thread pool queues linked list.
static constexpr int kAllQueuesList = 0;
// Thread pool queues linked list with excluded Background queues.
static constexpr int kOnlyNormalQueuesList = 1;
static constexpr int kQueuesListsCount = 2;
TaskQueueListEntry list_entries_[kQueuesListsCount];
// Only for Serial queues: non-null value means a task is currently processed.
bool *destroyed_flag_ = nullptr;
};
} // namespace base

View File

@ -280,6 +280,55 @@ weak_ptr<T> make_weak(const std::weak_ptr<T> &value) {
} // namespace base
namespace crl {
template <typename T, typename Enable>
struct guard_traits;
template <typename T>
struct guard_traits<base::weak_ptr<T>, void> {
static base::weak_ptr<T> create(const base::weak_ptr<T> &value) {
return value;
}
static base::weak_ptr<T> create(base::weak_ptr<T> &&value) {
return std::move(value);
}
static bool check(const base::weak_ptr<T> &guard) {
return guard.get() != nullptr;
}
};
template <typename T>
struct guard_traits<
T*,
std::enable_if_t<
std::is_base_of_v<base::has_weak_ptr, std::remove_cv_t<T>>>> {
static base::weak_ptr<T> create(T *value) {
return value;
}
static bool check(const base::weak_ptr<T> &guard) {
return guard.get() != nullptr;
}
};
template <typename T>
struct guard_traits<
gsl::not_null<T*>,
std::enable_if_t<
std::is_base_of_v<base::has_weak_ptr, std::remove_cv_t<T>>>> {
static base::weak_ptr<T> create(gsl::not_null<T*> value) {
return value.get();
}
static bool check(const base::weak_ptr<T> &guard) {
return guard.get() != nullptr;
}
};
} // namespace crl
#ifdef QT_VERSION
template <typename Lambda>
inline void InvokeQueued(const base::has_weak_ptr *context, Lambda &&lambda) {

View File

@ -37,7 +37,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "apiwrap.h"
#include "observer_peer.h"
#include "platform/platform_specific.h"
#include "base/task_queue.h"
#include "window/main_window.h"
namespace Calls {
@ -425,10 +424,8 @@ void Panel::showControls() {
void Panel::destroyDelayed() {
hide();
base::TaskQueue::Main().Put([weak = QPointer<Panel>(this)] {
if (weak) {
delete weak.data();
}
crl::on_main(this, [=] {
delete this;
});
}

View File

@ -23,7 +23,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
#include "storage/localstorage.h"
#include "platform/platform_file_utilities.h"
#include "base/task_queue.h"
#include "messenger.h"
bool filedialogGetSaveFile(
@ -99,13 +98,13 @@ QString filedialogNextFilename(
namespace File {
void OpenEmailLink(const QString &email) {
base::TaskQueue::Main().Put([email] {
crl::on_main([=] {
Platform::File::UnsafeOpenEmailLink(email);
});
}
void OpenWith(const QString &filepath, QPoint menuPosition) {
base::TaskQueue::Main().Put([filepath, menuPosition] {
crl::on_main([=] {
if (!Platform::File::UnsafeShowOpenWithDropdown(filepath, menuPosition)) {
if (!Platform::File::UnsafeShowOpenWith(filepath)) {
Platform::File::UnsafeLaunch(filepath);
@ -115,13 +114,13 @@ void OpenWith(const QString &filepath, QPoint menuPosition) {
}
void Launch(const QString &filepath) {
base::TaskQueue::Main().Put([filepath] {
crl::on_main([=] {
Platform::File::UnsafeLaunch(filepath);
});
}
void ShowInFolder(const QString &filepath) {
base::TaskQueue::Main().Put([filepath] {
crl::on_main([=] {
Platform::File::UnsafeShowInFolder(filepath);
});
}
@ -147,7 +146,7 @@ void GetOpenPath(
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
crl::on_main([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
const auto success = Platform::FileDialog::Get(
@ -178,7 +177,7 @@ void GetOpenPaths(
const QString &filter,
base::lambda<void(OpenResult &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
crl::on_main([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
const auto success = Platform::FileDialog::Get(
@ -206,7 +205,7 @@ void GetWritePath(
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
crl::on_main([=] {
auto file = QString();
if (filedialogGetSaveFile(file, caption, filter, initialPath)) {
if (callback) {
@ -223,7 +222,7 @@ void GetFolder(
const QString &initialPath,
base::lambda<void(QString &&result)> callback,
base::lambda<void()> failed) {
base::TaskQueue::Main().Put([=] {
crl::on_main([=] {
auto files = QStringList();
auto remoteContent = QByteArray();
const auto success = Platform::FileDialog::Get(

View File

@ -35,7 +35,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/layer_widget.h"
#include "lang/lang_keys.h"
#include "base/observer.h"
#include "base/task_queue.h"
#include "history/history_media.h"
#include "styles/style_history.h"
@ -508,20 +507,7 @@ void WorkingDirReady() {
}
}
object_ptr<SingleQueuedInvokation> MainThreadTaskHandler = { nullptr };
void MainThreadTaskAdded() {
if (!started()) {
return;
}
MainThreadTaskHandler->call();
}
void start() {
MainThreadTaskHandler.create([] {
base::TaskQueue::ProcessMainTasks();
});
SandboxData = std::make_unique<internal::Data>();
}
@ -531,7 +517,6 @@ bool started() {
void finish() {
SandboxData.reset();
MainThreadTaskHandler.destroy();
}
uint64 UserTag() {

View File

@ -111,10 +111,8 @@ void ActivateWindowDelayed(not_null<Window::Controller*> controller) {
const auto window = controller->window();
const auto weak = make_weak(window.get());
window->activateWindow();
crl::on_main([=] {
if (weak) {
weak->activateWindow();
}
crl::on_main(window, [=] {
window->activateWindow();
});
}

View File

@ -51,7 +51,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "window/themes/window_theme.h"
#include "window/themes/window_theme_warning.h"
#include "window/window_main_menu.h"
#include "base/task_queue.h"
#include "auth_session.h"
#include "window/window_controller.h"
@ -535,24 +534,23 @@ void MainWindow::themeUpdated(const Window::Theme::BackgroundUpdate &data) {
_testingThemeWarning->setGeometry(rect());
_testingThemeWarning->setHiddenCallback([this] { _testingThemeWarning.destroyDelayed(); });
}
base::TaskQueue::Main().Put(base::lambda_guarded(this, [this] {
crl::on_main(this, [=] {
if (_testingThemeWarning) {
_testingThemeWarning->showAnimated();
}
}));
});
} else if (data.type == Type::RevertingTheme || data.type == Type::ApplyingTheme) {
if (_testingThemeWarning) {
if (_testingThemeWarning->isHidden()) {
_testingThemeWarning.destroy();
} else {
base::TaskQueue::Main().Put(base::lambda_guarded(this, [this] {
crl::on_main(this, [=] {
if (_testingThemeWarning) {
_testingThemeWarning->hideAnimated();
_testingThemeWarning = nullptr;
}
setInnerFocus();
}));
});
}
}
}

View File

@ -26,7 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "media/media_audio_loaders.h"
#include "media/media_audio_track.h"
#include "platform/platform_audio.h"
#include "base/task_queue.h"
#include "messenger.h"
#include <AL/al.h>
#include <AL/alc.h>
@ -230,27 +230,35 @@ bool AttachToDevice() {
emit m->faderOnTimer();
}
base::TaskQueue::Main().Put([] {
Current().reattachTracks();
crl::on_main([] {
if (Messenger::InstancePointer()) {
Current().reattachTracks();
}
});
return true;
}
void ScheduleDetachFromDeviceSafe() {
base::TaskQueue::Main().Put([] {
Current().scheduleDetachFromDevice();
crl::on_main([] {
if (Messenger::InstancePointer()) {
Current().scheduleDetachFromDevice();
}
});
}
void ScheduleDetachIfNotUsedSafe() {
base::TaskQueue::Main().Put([] {
Current().scheduleDetachIfNotUsed();
crl::on_main([] {
if (Messenger::InstancePointer()) {
Current().scheduleDetachIfNotUsed();
}
});
}
void StopDetachIfNotUsedSafe() {
base::TaskQueue::Main().Put([] {
Current().stopDetachIfNotUsed();
crl::on_main([] {
if (Messenger::InstancePointer()) {
Current().stopDetachIfNotUsed();
}
});
}

View File

@ -36,7 +36,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_media_types.h"
#include "window/themes/window_theme_preview.h"
#include "window/window_peer_menu.h"
#include "base/task_queue.h"
#include "observer_peer.h"
#include "auth_session.h"
#include "messenger.h"
@ -1708,38 +1707,43 @@ void MediaView::initThemePreview() {
auto &location = _doc->location();
if (!location.isEmpty() && location.accessEnable()) {
_themePreviewShown = true;
auto path = _doc->location().name();
auto id = _themePreviewId = rand_value<uint64>();
auto ready = base::lambda_guarded(this, [this, id](std::unique_ptr<Window::Theme::Preview> result) {
if (id != _themePreviewId) {
return;
}
_themePreviewId = 0;
_themePreview = std::move(result);
if (_themePreview) {
_themeApply.create(this, langFactory(lng_theme_preview_apply), st::themePreviewApplyButton);
_themeApply->show();
_themeApply->setClickedCallback([this] {
auto preview = std::move(_themePreview);
close();
Window::Theme::Apply(std::move(preview));
});
_themeCancel.create(this, langFactory(lng_cancel), st::themePreviewCancelButton);
_themeCancel->show();
_themeCancel->setClickedCallback([this] { close(); });
updateControls();
}
update();
});
Window::Theme::CurrentData current;
current.backgroundId = Window::Theme::Background()->id();
current.backgroundImage = Window::Theme::Background()->pixmap();
current.backgroundTiled = Window::Theme::Background()->tile();
const auto path = _doc->location().name();
const auto id = _themePreviewId = rand_value<uint64>();
const auto weak = make_weak(this);
crl::async([=] {
auto preview = Window::Theme::GeneratePreview(path, current);
crl::on_main([ready, result = std::move(preview)]() mutable {
ready(std::move(result));
crl::on_main(weak, [=, result = std::move(preview)]() mutable {
if (id != _themePreviewId) {
return;
}
_themePreviewId = 0;
_themePreview = std::move(result);
if (_themePreview) {
_themeApply.create(
this,
langFactory(lng_theme_preview_apply),
st::themePreviewApplyButton);
_themeApply->show();
_themeApply->setClickedCallback([this] {
auto preview = std::move(_themePreview);
close();
Window::Theme::Apply(std::move(preview));
});
_themeCancel.create(
this,
langFactory(lng_cancel),
st::themePreviewCancelButton);
_themeCancel->show();
_themeCancel->setClickedCallback([this] { close(); });
updateControls();
}
update();
});
});
location.accessDisable();

View File

@ -24,7 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/linux/linux_libnotify.h"
#include "platform/linux/linux_libs.h"
#include "lang/lang_keys.h"
#include "base/task_queue.h"
namespace Platform {
namespace Notifications {
@ -203,10 +202,9 @@ private:
MsgId msgId = 0;
};
static void performOnMainQueue(NotificationDataStruct *data, base::lambda_once<void(Manager *manager)> task) {
base::TaskQueue::Main().Put([weak = data->weak, task = std::move(task)]() mutable {
if (auto strong = weak.lock()) {
task(*strong);
}
const auto weak = data->weak;
crl::on_main(weak, [=, task = std::move(task)]() mutable {
task(*weak.lock());
});
}
static void notificationDataFree(gpointer data) {

View File

@ -24,7 +24,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/mac/mac_utilities.h"
#include "styles/style_window.h"
#include "mainwindow.h"
#include "base/task_queue.h"
#include "base/variant.h"
#include <thread>
@ -87,7 +86,7 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm);
auto notificationManagerId = managerIdObject ? [managerIdObject unsignedLongLongValue] : 0ULL;
DEBUG_LOG(("Received notification with instance %1, mine: %2").arg(notificationManagerId).arg(_managerId));
if (notificationManagerId != _managerId) { // other app instance notification
base::TaskQueue::Main().Put([] {
crl::on_main([] {
// Usually we show and activate main window when the application
// is activated (receives applicationDidBecomeActive: notification).
//
@ -112,17 +111,15 @@ NSImage *qt_mac_create_nsimage(const QPixmap &pm);
NSNumber *msgObject = [notificationUserInfo objectForKey:@"msgid"];
auto notificationMsgId = msgObject ? [msgObject intValue] : 0;
if (notification.activationType == NSUserNotificationActivationTypeReplied) {
auto notificationReply = QString::fromUtf8([[[notification response] string] UTF8String]);
base::TaskQueue::Main().Put([manager = _manager, notificationPeerId, notificationMsgId, notificationReply] {
if (manager) {
manager->notificationReplied(notificationPeerId, notificationMsgId, notificationReply);
}
const auto notificationReply = QString::fromUtf8([[[notification response] string] UTF8String]);
const auto manager = _manager;
crl::on_main(manager, [=] {
manager->notificationReplied(notificationPeerId, notificationMsgId, notificationReply);
});
} else if (notification.activationType == NSUserNotificationActivationTypeContentsClicked) {
base::TaskQueue::Main().Put([manager = _manager, notificationPeerId, notificationMsgId] {
if (manager) {
manager->notificationActivated(notificationPeerId, notificationMsgId);
}
const auto manager = _manager;
crl::on_main(manager, [=] {
manager->notificationActivated(notificationPeerId, notificationMsgId);
});
}
@ -214,9 +211,9 @@ Manager::Private::Private(Manager *manager)
subscribe(Global::RefWorkMode(), [this](DBIWorkMode mode) {
// We need to update the delegate _after_ the tray icon change was done in Qt.
// Because Qt resets the delegate.
base::TaskQueue::Main().Put(base::lambda_guarded(this, [this] {
crl::on_main(this, [=] {
updateDelegate();
}));
});
});
}

View File

@ -25,7 +25,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "platform/win/windows_event_filter.h"
#include "platform/win/windows_dlls.h"
#include "mainwindow.h"
#include "base/task_queue.h"
#include <Shobjidl.h>
#include <shellapi.h>
@ -226,10 +225,9 @@ public:
~ToastEventHandler() = default;
void performOnMainQueue(base::lambda_once<void(Manager *manager)> task) {
base::TaskQueue::Main().Put([weak = _weak, task = std::move(task)]() mutable {
if (auto strong = weak.lock()) {
task(*strong);
}
const auto weak = _weak;
crl::on_main(weak, [=, task = std::move(task)]() mutable {
task(*weak.lock());
});
}

View File

@ -31,7 +31,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "history/history_location_manager.h"
#include "storage/localstorage.h"
#include "passcodewidget.h"
#include "base/task_queue.h"
#include "core/crash_reports.h"
#include <Shobjidl.h>

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/storage_media_prepare.h"
#include "platform/platform_file_utilities.h"
#include "base/task_queue.h"
#include "storage/localimageloader.h"
namespace Storage {
@ -58,8 +57,8 @@ bool PrepareAlbumMediaIsWaiting(
QSemaphore &semaphore,
PreparedFile &file,
int previewWidth) {
// Use some special thread queue, like a separate QThreadPool.
base::TaskQueue::Normal().Put([&, previewWidth] {
// TODO: Use some special thread queue, like a separate QThreadPool.
crl::async([=, &semaphore, &file] {
const auto guard = gsl::finally([&] { semaphore.release(); });
if (!file.path.isEmpty()) {
file.mime = mimeTypeForFile(QFileInfo(file.path)).name();

View File

@ -21,7 +21,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "storage/storage_shared_media.h"
#include <rpl/map.h>
#include "base/task_queue.h"
namespace Storage {

View File

@ -20,8 +20,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
*/
#include "storage/storage_user_photos.h"
#include "base/task_queue.h"
namespace Storage {
void UserPhotos::List::addNew(PhotoId photoId) {

View File

@ -35,7 +35,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/checkbox.h"
#include "ui/widgets/multi_select.h"
#include "base/parse_helper.h"
#include "base/task_queue.h"
#include "base/zlib_help.h"
#include "ui/toast/toast.h"
#include "core/file_utilities.h"
@ -718,7 +717,9 @@ Editor::Editor(QWidget*, const QString &path)
// This could be from inner->_context observable notification.
// We should not destroy it while iterating in subscribers.
base::TaskQueue::Main().Put(base::lambda_guarded(this, [this] { closeEditor(); }));
crl::on_main(this, [=] {
closeEditor();
});
});
_inner->setFocusCallback([this] {
App::CallDelayed(2 * st::boxDuration, this, [this] { _select->setInnerFocus(); });

@ -1 +1 @@
Subproject commit 9e11a5c9291760d03df559d03d81fa7afdd0a46d
Subproject commit 705a5fd6166fd577d6a95cef9d74f7aa0c4ec3ed

View File

@ -52,6 +52,7 @@
'<(crl_src_loc)/common/crl_common_list.h',
'<(crl_src_loc)/common/crl_common_on_main.cpp',
'<(crl_src_loc)/common/crl_common_on_main.h',
'<(crl_src_loc)/common/crl_common_on_main_guarded.h',
'<(crl_src_loc)/common/crl_common_queue.cpp',
'<(crl_src_loc)/common/crl_common_queue.h',
'<(crl_src_loc)/common/crl_common_sync.h',

View File

@ -22,8 +22,6 @@
<(src_loc)/base/qthelp_url.h
<(src_loc)/base/runtime_composer.cpp
<(src_loc)/base/runtime_composer.h
<(src_loc)/base/task_queue.cpp
<(src_loc)/base/task_queue.h
<(src_loc)/base/timer.cpp
<(src_loc)/base/timer.h
<(src_loc)/base/type_traits.h