aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/libmysql_r/include/my_systime.h
blob: 53fd31202659dca6ecdfe9cb514026174ab4ccac (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
   Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License, version 2.0,
   as published by the Free Software Foundation.

   This program is also distributed with certain software (including
   but not limited to OpenSSL) that is licensed under separate terms,
   as designated in a particular file or component or in included license
   documentation.  The authors of MySQL hereby grant you an additional
   permission to link the program and your derivative works with the
   separately licensed software that they have included with MySQL.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License, version 2.0, for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */

#ifndef MY_SYSTIME_INCLUDED
#define MY_SYSTIME_INCLUDED

/**
  @file include/my_systime.h
  Defines for getting and processing the current system type programmatically.
*/

#include <time.h>   // time_t, struct timespec (C11/C++17)
#include <chrono>   // std::chrono::microseconds
#include <cstdint>  // std::int64_t
#include <limits>   // std::numeric_limits
#include <thread>   // std::this_thread::wait_for

#include "my_config.h"

#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>  // clock_gettime()
#endif                 /* HAVE_SYS_TIME_H */

using UTC_clock = std::chrono::system_clock;

/* Bits for get_date timeflag */
constexpr const int GETDATE_DATE_TIME = 1;
constexpr const int GETDATE_SHORT_DATE = 2;
constexpr const int GETDATE_HHMMSSTIME = 4;
constexpr const int GETDATE_GMT = 8;
constexpr const int GETDATE_FIXEDLENGTH = 16;
constexpr const int GETDATE_T_DELIMITER = 32;
constexpr const int GETDATE_SHORT_DATE_FULL_YEAR = 64;

/**
   Wait a given number of microseconds.

   @param m_seconds number of microseconds to wait.
*/
inline void my_sleep(time_t m_seconds) {
  std::this_thread::sleep_for(std::chrono::microseconds{m_seconds});
}

#ifdef _WIN32

#include <windows.h>

/****************************************************************************
** Replacements for localtime_r and gmtime_r
****************************************************************************/

inline static struct tm *localtime_r(const time_t *timep, struct tm *tmp) {
  localtime_s(tmp, timep);
  return tmp;
}

inline static struct tm *gmtime_r(const time_t *clock, struct tm *res) {
  gmtime_s(res, clock);
  return res;
}

/**
   Sleep the given number of seconds. POSIX compatibility.

   @param seconds number of seconds to wait
*/
inline void sleep(unsigned long seconds) {
  std::this_thread::sleep_for(std::chrono::seconds{seconds});
}

#endif /* _WIN32 */

/**
  Get high-resolution time. Forwards to std::chrono.

  @deprecated New code should use std::chrono directly.

  @return current high-resolution time in multiples of 100 nanoseconds.
*/
inline unsigned long long int my_getsystime() {
#ifdef HAVE_CLOCK_GETTIME
  // Performance regression testing showed this to be preferable
  struct timespec tp;
  clock_gettime(CLOCK_REALTIME, &tp);
  return (static_cast<unsigned long long int>(tp.tv_sec) * 10000000 +
          static_cast<unsigned long long int>(tp.tv_nsec) / 100);
#else
  return std::chrono::duration_cast<
             std::chrono::duration<std::int64_t, std::ratio<1, 10000000>>>(
             UTC_clock::now().time_since_epoch())
      .count();
#endif /* HAVE_CLOCK_GETTIME */
}

/**
   The maximum timespec value used to represent "inifinity" (as when
   requesting an "inifinite" timeout.
 */
constexpr const timespec TIMESPEC_POSINF = {
    std::numeric_limits<decltype(timespec::tv_sec)>::max(), 999999999};

/** Type alias to reduce chance of coversion errors on timeout values. */
using Timeout_type = std::uint64_t;

/** Value representing "infinite" timeout. */
constexpr const Timeout_type TIMEOUT_INF =
    std::numeric_limits<Timeout_type>::max() - 1;

void set_timespec_nsec(struct timespec *abstime, Timeout_type nsec);
void set_timespec(struct timespec *abstime, Timeout_type sec);
timespec timespec_now();

/**
   Compare two timespec structs.

   @retval  1 If ts1 ends after ts2.
   @retval -1 If ts1 ends before ts2.
   @retval  0 If ts1 is equal to ts2.
*/
inline int cmp_timespec(struct timespec *ts1, struct timespec *ts2) {
  if (ts1->tv_sec > ts2->tv_sec ||
      (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec > ts2->tv_nsec))
    return 1;
  if (ts1->tv_sec < ts2->tv_sec ||
      (ts1->tv_sec == ts2->tv_sec && ts1->tv_nsec < ts2->tv_nsec))
    return -1;
  return 0;
}

/**
   Calculate the diff between two timespec values.

   @return difference in nanoseconds between ts1 and ts2
*/
inline unsigned long long int diff_timespec(struct timespec *ts1,
                                            struct timespec *ts2) {
  return (ts1->tv_sec - ts2->tv_sec) * 1000000000ULL + ts1->tv_nsec -
         ts2->tv_nsec;
}

/**
  Return current time. Takes an int argument
  for backward compatibility. This argument is ignored.

  @deprecated New code should use std::time() directly.

  @retval current time.
*/
inline time_t my_time(int) { return time(nullptr); }

/**
  Return time in microseconds. Uses std::chrono::high_resolution_clock

  @remark This function is to be used to measure performance in
          micro seconds.

  @deprecated New code should use std::chrono directly.

  @retval Number of microseconds since the Epoch, 1970-01-01 00:00:00 +0000
  (UTC)
*/
inline unsigned long long int my_micro_time() {
#ifdef _WIN32
  return std::chrono::duration_cast<std::chrono::microseconds>(
             UTC_clock::now().time_since_epoch())
      .count();
#else
  struct timeval t;
  /*
  The following loop is here because gettimeofday may fail on some systems
  */
  while (gettimeofday(&t, nullptr) != 0) {
  }
  return (static_cast<unsigned long long int>(t.tv_sec) * 1000000 + t.tv_usec);
#endif /* _WIN32 */
}

void get_date(char *to, int flag, time_t date);

#endif  // MY_SYSTIME_INCLUDED