my_systime.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License, version 2.0,
  5. as published by the Free Software Foundation.
  6. This program is also distributed with certain software (including
  7. but not limited to OpenSSL) that is licensed under separate terms,
  8. as designated in a particular file or component or in included license
  9. documentation. The authors of MySQL hereby grant you an additional
  10. permission to link the program and your derivative works with the
  11. separately licensed software that they have included with MySQL.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License, version 2.0, for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
  19. #ifndef MY_SYSTIME_INCLUDED
  20. #define MY_SYSTIME_INCLUDED
  21. /**
  22. @file include/my_systime.h
  23. Defines for getting and processing the current system type programmatically.
  24. */
  25. #include <time.h> // time_t, struct timespec (C11/C++17)
  26. #include <chrono> // std::chrono::microseconds
  27. #include <cstdint> // std::int64_t
  28. #include <limits> // std::numeric_limits
  29. #include <thread> // std::this_thread::wait_for
  30. #include "my_config.h"
  31. #ifdef HAVE_SYS_TIME_H
  32. #include <sys/time.h> // clock_gettime()
  33. #endif /* HAVE_SYS_TIME_H */
  34. using UTC_clock = std::chrono::system_clock;
  35. /* Bits for get_date timeflag */
  36. constexpr const int GETDATE_DATE_TIME = 1;
  37. constexpr const int GETDATE_SHORT_DATE = 2;
  38. constexpr const int GETDATE_HHMMSSTIME = 4;
  39. constexpr const int GETDATE_GMT = 8;
  40. constexpr const int GETDATE_FIXEDLENGTH = 16;
  41. constexpr const int GETDATE_T_DELIMITER = 32;
  42. constexpr const int GETDATE_SHORT_DATE_FULL_YEAR = 64;
  43. /**
  44. Wait a given number of microseconds.
  45. @param m_seconds number of microseconds to wait.
  46. */
  47. inline void my_sleep(time_t m_seconds) {
  48. std::this_thread::sleep_for(std::chrono::microseconds{m_seconds});
  49. }
  50. #ifdef _WIN32
  51. #include <windows.h>
  52. /****************************************************************************
  53. ** Replacements for localtime_r and gmtime_r
  54. ****************************************************************************/
  55. inline static struct tm *localtime_r(const time_t *timep, struct tm *tmp) {
  56. localtime_s(tmp, timep);
  57. return tmp;
  58. }
  59. inline static struct tm *gmtime_r(const time_t *clock, struct tm *res) {
  60. gmtime_s(res, clock);
  61. return res;
  62. }
  63. /**
  64. Sleep the given number of seconds. POSIX compatibility.
  65. @param seconds number of seconds to wait
  66. */
  67. inline void sleep(unsigned long seconds) {
  68. std::this_thread::sleep_for(std::chrono::seconds{seconds});
  69. }
  70. #endif /* _WIN32 */
  71. /**
  72. Get high-resolution time. Forwards to std::chrono.
  73. @deprecated New code should use std::chrono directly.
  74. @return current high-resolution time in multiples of 100 nanoseconds.
  75. */
  76. inline unsigned long long int my_getsystime() {
  77. #ifdef HAVE_CLOCK_GETTIME
  78. // Performance regression testing showed this to be preferable
  79. struct timespec tp;
  80. clock_gettime(CLOCK_REALTIME, &tp);
  81. return (static_cast<unsigned long long int>(tp.tv_sec) * 10000000 +
  82. static_cast<unsigned long long int>(tp.tv_nsec) / 100);
  83. #else
  84. return std::chrono::duration_cast<
  85. std::chrono::duration<std::int64_t, std::ratio<1, 10000000>>>(
  86. UTC_clock::now().time_since_epoch())
  87. .count();
  88. #endif /* HAVE_CLOCK_GETTIME */
  89. }
  90. /**
  91. The maximum timespec value used to represent "inifinity" (as when
  92. requesting an "inifinite" timeout.
  93. */
  94. constexpr const timespec TIMESPEC_POSINF = {
  95. std::numeric_limits<decltype(timespec::tv_sec)>::max(), 999999999};
  96. /** Type alias to reduce chance of coversion errors on timeout values. */
  97. using Timeout_type = std::uint64_t;
  98. /** Value representing "infinite" timeout. */
  99. constexpr const Timeout_type TIMEOUT_INF =
  100. std::numeric_limits<Timeout_type>::max() - 1;
  101. void set_timespec_nsec(struct timespec *abstime, Timeout_type nsec);
  102. void set_timespec(struct timespec *abstime, Timeout_type sec);
  103. timespec timespec_now();
  104. /**
  105. Compare two timespec structs.
  106. @retval 1 If ts1 ends after ts2.
  107. @retval -1 If ts1 ends before ts2.
  108. @retval 0 If ts1 is equal to ts2.
  109. */
  110. inline int cmp_timespec(struct timespec *ts1, struct timespec *ts2) {
  111. if (ts1->tv_sec > ts2->tv_sec ||
  112. (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec > ts2->tv_nsec))
  113. return 1;
  114. if (ts1->tv_sec < ts2->tv_sec ||
  115. (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec < ts2->tv_nsec))
  116. return -1;
  117. return 0;
  118. }
  119. /**
  120. Calculate the diff between two timespec values.
  121. @return difference in nanoseconds between ts1 and ts2
  122. */
  123. inline unsigned long long int diff_timespec(struct timespec *ts1,
  124. struct timespec *ts2) {
  125. return (ts1->tv_sec - ts2->tv_sec) * 1000000000ULL + ts1->tv_nsec -
  126. ts2->tv_nsec;
  127. }
  128. /**
  129. Return current time. Takes an int argument
  130. for backward compatibility. This argument is ignored.
  131. @deprecated New code should use std::time() directly.
  132. @retval current time.
  133. */
  134. inline time_t my_time(int) { return time(nullptr); }
  135. /**
  136. Return time in microseconds. Uses std::chrono::high_resolution_clock
  137. @remark This function is to be used to measure performance in
  138. micro seconds.
  139. @deprecated New code should use std::chrono directly.
  140. @retval Number of microseconds since the Epoch, 1970-01-01 00:00:00 +0000
  141. (UTC)
  142. */
  143. inline unsigned long long int my_micro_time() {
  144. #ifdef _WIN32
  145. return std::chrono::duration_cast<std::chrono::microseconds>(
  146. UTC_clock::now().time_since_epoch())
  147. .count();
  148. #else
  149. struct timeval t;
  150. /*
  151. The following loop is here because gettimeofday may fail on some systems
  152. */
  153. while (gettimeofday(&t, nullptr) != 0) {
  154. }
  155. return (static_cast<unsigned long long int>(t.tv_sec) * 1000000 + t.tv_usec);
  156. #endif /* _WIN32 */
  157. }
  158. void get_date(char *to, int flag, time_t date);
  159. #endif // MY_SYSTIME_INCLUDED