concurrent_timer.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. #pragma once
  8. #include "base/binary_guard.h"
  9. #include <crl/crl_time.h>
  10. #include <crl/crl_object_on_queue.h>
  11. #include <QtCore/QThread>
  12. namespace base {
  13. namespace details {
  14. class TimerObject;
  15. class TimerObjectWrap {
  16. public:
  17. explicit TimerObjectWrap(Fn<void()> adjust);
  18. ~TimerObjectWrap();
  19. void call(
  20. crl::time timeout,
  21. Qt::TimerType type,
  22. FnMut<void()> method);
  23. void cancel();
  24. private:
  25. void sendEvent(std::unique_ptr<QEvent> event);
  26. std::unique_ptr<TimerObject> _value;
  27. };
  28. } // namespace details
  29. class ConcurrentTimerEnvironment {
  30. public:
  31. ConcurrentTimerEnvironment();
  32. ~ConcurrentTimerEnvironment();
  33. std::unique_ptr<details::TimerObject> createTimer(Fn<void()> adjust);
  34. static void Adjust();
  35. private:
  36. void acquire();
  37. void release();
  38. void adjustTimers();
  39. QThread _thread;
  40. QObject _adjuster;
  41. };
  42. class ConcurrentTimer {
  43. public:
  44. explicit ConcurrentTimer(
  45. Fn<void(FnMut<void()>)> runner,
  46. Fn<void()> callback = nullptr);
  47. template <typename Policy, typename Object>
  48. explicit ConcurrentTimer(
  49. crl::details::weak_async<Policy, Object> weak,
  50. Fn<void()> callback = nullptr);
  51. static Qt::TimerType DefaultType(crl::time timeout) {
  52. constexpr auto kThreshold = crl::time(1000);
  53. return (timeout > kThreshold) ? Qt::CoarseTimer : Qt::PreciseTimer;
  54. }
  55. void setCallback(Fn<void()> callback) {
  56. _callback = std::move(callback);
  57. }
  58. void callOnce(crl::time timeout) {
  59. callOnce(timeout, DefaultType(timeout));
  60. }
  61. void callEach(crl::time timeout) {
  62. callEach(timeout, DefaultType(timeout));
  63. }
  64. void callOnce(crl::time timeout, Qt::TimerType type) {
  65. start(timeout, type, Repeat::SingleShot);
  66. }
  67. void callEach(crl::time timeout, Qt::TimerType type) {
  68. start(timeout, type, Repeat::Interval);
  69. }
  70. bool isActive() const {
  71. return _running.alive();
  72. }
  73. void cancel();
  74. crl::time remainingTime() const;
  75. private:
  76. enum class Repeat : unsigned {
  77. Interval = 0,
  78. SingleShot = 1,
  79. };
  80. Fn<void()> createAdjuster();
  81. void start(crl::time timeout, Qt::TimerType type, Repeat repeat);
  82. void adjust();
  83. void cancelAndSchedule(int timeout);
  84. void setTimeout(crl::time timeout);
  85. int timeout() const;
  86. void timerEvent();
  87. void setRepeat(Repeat repeat) {
  88. _repeat = static_cast<unsigned>(repeat);
  89. }
  90. Repeat repeat() const {
  91. return static_cast<Repeat>(_repeat);
  92. }
  93. Fn<void(FnMut<void()>)> _runner;
  94. std::shared_ptr<bool> _guard; // Must be before _object.
  95. details::TimerObjectWrap _object;
  96. Fn<void()> _callback;
  97. base::binary_guard _running;
  98. crl::time _next = 0;
  99. int _timeout = 0;
  100. Qt::TimerType _type : 2;
  101. bool _adjusted : 1 = false;
  102. unsigned _repeat : 1 = 0;
  103. };
  104. template <typename Policy, typename Object>
  105. ConcurrentTimer::ConcurrentTimer(
  106. crl::details::weak_async<Policy, Object> weak,
  107. Fn<void()> callback)
  108. : ConcurrentTimer(weak.runner(), std::move(callback)) {
  109. }
  110. } // namespace base