deadlock_detector.h 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #pragma once
  8. namespace Core::DeadlockDetector {
  9. class PingPongEvent : public QEvent {
  10. public:
  11. static auto Type() {
  12. static const auto Result = QEvent::Type(QEvent::registerEventType());
  13. return Result;
  14. }
  15. PingPongEvent(not_null<QObject*> sender)
  16. : QEvent(Type())
  17. , _sender(sender) {
  18. }
  19. [[nodiscard]] not_null<QObject*> sender() const {
  20. return _sender;
  21. }
  22. private:
  23. not_null<QObject*> _sender;
  24. };
  25. class Pinger : public QObject {
  26. public:
  27. Pinger(not_null<QObject*> receiver)
  28. : _receiver(receiver)
  29. , _abortTimer([] { Unexpected("Deadlock found!"); }) {
  30. const auto callback = [=] {
  31. QCoreApplication::postEvent(_receiver, new PingPongEvent(this));
  32. _abortTimer.callOnce(30000);
  33. };
  34. _pingTimer.setCallback(callback);
  35. _pingTimer.callEach(60000);
  36. callback();
  37. }
  38. protected:
  39. bool event(QEvent *e) override {
  40. if (e->type() == PingPongEvent::Type()
  41. && static_cast<PingPongEvent*>(e)->sender() == _receiver) {
  42. _abortTimer.cancel();
  43. }
  44. return QObject::event(e);
  45. }
  46. private:
  47. not_null<QObject*> _receiver;
  48. base::Timer _pingTimer;
  49. base::Timer _abortTimer;
  50. };
  51. class PingThread : public QThread {
  52. public:
  53. PingThread(not_null<QObject*> parent)
  54. : QThread(parent) {
  55. start();
  56. }
  57. ~PingThread() {
  58. quit();
  59. wait();
  60. }
  61. protected:
  62. void run() override {
  63. Pinger pinger(parent());
  64. QThread::run();
  65. }
  66. };
  67. } // namespace Core::DeadlockDetector