timer.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 "base/timer.h"
  8. #include "base/concurrent_timer.h"
  9. #include "base/unixtime.h"
  10. #include <QtCore/QTimerEvent>
  11. namespace base {
  12. namespace {
  13. QObject *TimersAdjuster() {
  14. static QObject adjuster;
  15. return &adjuster;
  16. }
  17. } // namespace
  18. void CheckLocalTime() {
  19. if (crl::adjust_time()) {
  20. base::Timer::Adjust();
  21. base::ConcurrentTimerEnvironment::Adjust();
  22. base::unixtime::http_invalidate();
  23. }
  24. }
  25. Timer::Timer(
  26. not_null<QThread*> thread,
  27. Fn<void()> callback)
  28. : Timer(std::move(callback)) {
  29. moveToThread(thread);
  30. }
  31. Timer::Timer(Fn<void()> callback)
  32. : QObject(nullptr)
  33. , _callback(std::move(callback))
  34. , _type(Qt::PreciseTimer) {
  35. setRepeat(Repeat::Interval);
  36. connect(
  37. TimersAdjuster(),
  38. &QObject::destroyed,
  39. this,
  40. [this] { adjust(); },
  41. Qt::QueuedConnection);
  42. }
  43. void Timer::start(crl::time timeout, Qt::TimerType type, Repeat repeat) {
  44. cancel();
  45. _type = type;
  46. setRepeat(repeat);
  47. _adjusted = false;
  48. setTimeout(timeout);
  49. _timerId = startTimer(_timeout, _type);
  50. if (_timerId) {
  51. _next = crl::now() + _timeout;
  52. } else {
  53. _next = 0;
  54. }
  55. }
  56. void Timer::cancel() {
  57. if (isActive()) {
  58. killTimer(base::take(_timerId));
  59. }
  60. }
  61. crl::time Timer::remainingTime() const {
  62. if (!isActive()) {
  63. return -1;
  64. }
  65. const auto now = crl::now();
  66. return (_next > now) ? (_next - now) : crl::time(0);
  67. }
  68. void Timer::Adjust() {
  69. QObject emitter;
  70. connect(
  71. &emitter,
  72. &QObject::destroyed,
  73. TimersAdjuster(),
  74. &QObject::destroyed);
  75. }
  76. void Timer::adjust() {
  77. auto remaining = remainingTime();
  78. if (remaining >= 0) {
  79. cancel();
  80. _timerId = startTimer(remaining, _type);
  81. _adjusted = true;
  82. }
  83. }
  84. void Timer::setTimeout(crl::time timeout) {
  85. Expects(timeout >= 0 && timeout <= std::numeric_limits<int>::max());
  86. _timeout = static_cast<unsigned int>(timeout);
  87. }
  88. int Timer::timeout() const {
  89. return _timeout;
  90. }
  91. void Timer::timerEvent(QTimerEvent *e) {
  92. if (repeat() == Repeat::Interval) {
  93. if (_adjusted) {
  94. start(_timeout, _type, repeat());
  95. } else {
  96. _next = crl::now() + _timeout;
  97. }
  98. } else {
  99. cancel();
  100. }
  101. if (const auto onstack = _callback) {
  102. onstack();
  103. }
  104. }
  105. int DelayedCallTimer::call(
  106. crl::time timeout,
  107. FnMut<void()> callback,
  108. Qt::TimerType type) {
  109. Expects(timeout >= 0);
  110. if (!callback) {
  111. return 0;
  112. }
  113. auto timerId = startTimer(static_cast<int>(timeout), type);
  114. if (timerId) {
  115. _callbacks.emplace(timerId, std::move(callback));
  116. }
  117. return timerId;
  118. }
  119. void DelayedCallTimer::cancel(int callId) {
  120. if (callId) {
  121. killTimer(callId);
  122. _callbacks.remove(callId);
  123. }
  124. }
  125. void DelayedCallTimer::timerEvent(QTimerEvent *e) {
  126. auto timerId = e->timerId();
  127. killTimer(timerId);
  128. auto it = _callbacks.find(timerId);
  129. if (it != _callbacks.end()) {
  130. auto callback = std::move(it->second);
  131. _callbacks.erase(it);
  132. callback();
  133. }
  134. }
  135. } // namespace base