main_queue_processor.cpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "ui/main_queue_processor.h"
  8. #include "base/integration.h"
  9. #include "ui/platform/ui_platform_utility.h"
  10. #include <QtCore/QMutex>
  11. #include <QtCore/QCoreApplication>
  12. #include <QtGui/QtEvents>
  13. #include <crl/crl_on_main.h>
  14. namespace Ui {
  15. namespace {
  16. auto ProcessorEventType() {
  17. static const auto Result = QEvent::Type(QEvent::registerEventType());
  18. return Result;
  19. }
  20. QMutex ProcessorMutex;
  21. MainQueueProcessor *ProcessorInstance/* = nullptr*/;
  22. enum class ProcessState : int {
  23. Processed,
  24. FillingUp,
  25. Waiting,
  26. };
  27. std::atomic<ProcessState> MainQueueProcessState/* = ProcessState(0)*/;
  28. void (*MainQueueProcessCallback)(void*)/* = nullptr*/;
  29. void *MainQueueProcessArgument/* = nullptr*/;
  30. void PushToMainQueueGeneric(void (*callable)(void*), void *argument) {
  31. Expects(Platform::UseMainQueueGeneric());
  32. auto expected = ProcessState::Processed;
  33. const auto fill = MainQueueProcessState.compare_exchange_strong(
  34. expected,
  35. ProcessState::FillingUp);
  36. if (fill) {
  37. MainQueueProcessCallback = callable;
  38. MainQueueProcessArgument = argument;
  39. MainQueueProcessState.store(ProcessState::Waiting);
  40. }
  41. auto event = std::make_unique<QEvent>(ProcessorEventType());
  42. QMutexLocker lock(&ProcessorMutex);
  43. if (ProcessorInstance) {
  44. QCoreApplication::postEvent(ProcessorInstance, event.release());
  45. }
  46. }
  47. void DrainMainQueueGeneric() {
  48. Expects(Platform::UseMainQueueGeneric());
  49. if (MainQueueProcessState.load() != ProcessState::Waiting) {
  50. return;
  51. }
  52. const auto callback = MainQueueProcessCallback;
  53. const auto argument = MainQueueProcessArgument;
  54. MainQueueProcessState.store(ProcessState::Processed);
  55. callback(argument);
  56. }
  57. } // namespace
  58. MainQueueProcessor::MainQueueProcessor() {
  59. if constexpr (Platform::UseMainQueueGeneric()) {
  60. acquire();
  61. crl::init_main_queue(PushToMainQueueGeneric);
  62. } else {
  63. crl::wrap_main_queue([](void (*callable)(void*), void *argument) {
  64. base::Integration::Instance().enterFromEventLoop([&] {
  65. callable(argument);
  66. });
  67. });
  68. }
  69. crl::on_main_update_requests(
  70. ) | rpl::start_with_next([] {
  71. if constexpr (Platform::UseMainQueueGeneric()) {
  72. DrainMainQueueGeneric();
  73. } else {
  74. Platform::DrainMainQueue();
  75. }
  76. }, _lifetime);
  77. }
  78. bool MainQueueProcessor::event(QEvent *event) {
  79. if constexpr (Platform::UseMainQueueGeneric()) {
  80. if (event->type() == ProcessorEventType()) {
  81. DrainMainQueueGeneric();
  82. return true;
  83. }
  84. }
  85. return QObject::event(event);
  86. }
  87. void MainQueueProcessor::acquire() {
  88. Expects(Platform::UseMainQueueGeneric());
  89. Expects(ProcessorInstance == nullptr);
  90. QMutexLocker lock(&ProcessorMutex);
  91. ProcessorInstance = this;
  92. }
  93. void MainQueueProcessor::release() {
  94. Expects(Platform::UseMainQueueGeneric());
  95. Expects(ProcessorInstance == this);
  96. QMutexLocker lock(&ProcessorMutex);
  97. ProcessorInstance = nullptr;
  98. }
  99. MainQueueProcessor::~MainQueueProcessor() {
  100. if constexpr (Platform::UseMainQueueGeneric()) {
  101. release();
  102. }
  103. }
  104. } // namespace Ui