You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Timer.cxx 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2016-2018 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. // -=- Timer.cxx
  20. #ifdef HAVE_CONFIG_H
  21. #include <config.h>
  22. #endif
  23. #include <stdio.h>
  24. #include <sys/time.h>
  25. #include <rfb/Timer.h>
  26. #include <rfb/util.h>
  27. #include <rfb/LogWriter.h>
  28. using namespace rfb;
  29. #ifndef __NO_DEFINE_VLOG__
  30. static LogWriter vlog("Timer");
  31. #endif
  32. // Millisecond timeout processing helper functions
  33. inline static timeval addMillis(timeval inTime, int millis) {
  34. int secs = millis / 1000;
  35. millis = millis % 1000;
  36. inTime.tv_sec += secs;
  37. inTime.tv_usec += millis * 1000;
  38. if (inTime.tv_usec >= 1000000) {
  39. inTime.tv_sec++;
  40. inTime.tv_usec -= 1000000;
  41. }
  42. return inTime;
  43. }
  44. inline static int diffTimeMillis(timeval later, timeval earlier) {
  45. return ((later.tv_sec - earlier.tv_sec) * 1000) + ((later.tv_usec - earlier.tv_usec) / 1000);
  46. }
  47. std::list<Timer*> Timer::pending;
  48. int Timer::checkTimeouts() {
  49. timeval start;
  50. if (pending.empty())
  51. return 0;
  52. gettimeofday(&start, 0);
  53. while (pending.front()->isBefore(start)) {
  54. Timer* timer;
  55. timeval before;
  56. timer = pending.front();
  57. pending.pop_front();
  58. gettimeofday(&before, 0);
  59. if (timer->cb->handleTimeout(timer)) {
  60. timeval now;
  61. gettimeofday(&now, 0);
  62. timer->dueTime = addMillis(timer->dueTime, timer->timeoutMs);
  63. if (timer->isBefore(now)) {
  64. // Time has jumped forwards, or we're not getting enough
  65. // CPU time for the timers
  66. timer->dueTime = addMillis(before, timer->timeoutMs);
  67. if (timer->isBefore(now))
  68. timer->dueTime = now;
  69. }
  70. insertTimer(timer);
  71. } else if (pending.empty()) {
  72. return 0;
  73. }
  74. }
  75. return getNextTimeout();
  76. }
  77. int Timer::getNextTimeout() {
  78. timeval now;
  79. gettimeofday(&now, 0);
  80. int toWait = __rfbmax(1, pending.front()->getRemainingMs());
  81. if (toWait > pending.front()->timeoutMs) {
  82. if (toWait - pending.front()->timeoutMs < 1000) {
  83. vlog.info("gettimeofday is broken...");
  84. return toWait;
  85. }
  86. // Time has jumped backwards!
  87. vlog.info("time has moved backwards!");
  88. pending.front()->dueTime = now;
  89. toWait = 1;
  90. }
  91. return toWait;
  92. }
  93. void Timer::insertTimer(Timer* t) {
  94. std::list<Timer*>::iterator i;
  95. for (i=pending.begin(); i!=pending.end(); i++) {
  96. if (t->isBefore((*i)->dueTime)) {
  97. pending.insert(i, t);
  98. return;
  99. }
  100. }
  101. pending.push_back(t);
  102. }
  103. void Timer::start(int timeoutMs_) {
  104. timeval now;
  105. gettimeofday(&now, 0);
  106. stop();
  107. timeoutMs = timeoutMs_;
  108. // The rest of the code assumes non-zero timeout
  109. if (timeoutMs <= 0)
  110. timeoutMs = 1;
  111. dueTime = addMillis(now, timeoutMs);
  112. insertTimer(this);
  113. }
  114. void Timer::stop() {
  115. pending.remove(this);
  116. }
  117. bool Timer::isStarted() {
  118. std::list<Timer*>::iterator i;
  119. for (i=pending.begin(); i!=pending.end(); i++) {
  120. if (*i == this)
  121. return true;
  122. }
  123. return false;
  124. }
  125. int Timer::getTimeoutMs() {
  126. return timeoutMs;
  127. }
  128. int Timer::getRemainingMs() {
  129. timeval now;
  130. gettimeofday(&now, 0);
  131. return __rfbmax(0, diffTimeMillis(dueTime, now));
  132. }
  133. bool Timer::isBefore(timeval other) {
  134. return (dueTime.tv_sec < other.tv_sec) ||
  135. ((dueTime.tv_sec == other.tv_sec) &&
  136. (dueTime.tv_usec < other.tv_usec));
  137. }