gh-110850: Add PyTime_t C API (GH-115215) · python/cpython@879f454

GitHub

@@ -1,45 +1,51 @@

1-// The _PyTime_t API is written to use timestamp and timeout values stored in

2-// various formats and to read clocks.

1+// Internal PyTime_t C API: see Doc/c-api/time.rst for the documentation.

32//

4-// The _PyTime_t type is an integer to support directly common arithmetic

5-// operations like t1 + t2.

3+// The PyTime_t type is an integer to support directly common arithmetic

4+// operations such as t1 + t2.

65//

7-// The _PyTime_t API supports a resolution of 1 nanosecond. The _PyTime_t type

8-// is signed to support negative timestamps. The supported range is around

9-// [-292.3 years; +292.3 years]. Using the Unix epoch (January 1st, 1970), the

10-// supported date range is around [1677-09-21; 2262-04-11].

6+// Time formats:

117//

12-// Formats:

8+// * Seconds.

9+// * Seconds as a floating point number (C double).

10+// * Milliseconds (10^-3 seconds).

11+// * Microseconds (10^-6 seconds).

12+// * 100 nanoseconds (10^-7 seconds), used on Windows.

13+// * Nanoseconds (10^-9 seconds).

14+// * timeval structure, 1 microsecond (10^-6 seconds).

15+// * timespec structure, 1 nanosecond (10^-9 seconds).

1316//

14-// * seconds

15-// * seconds as a floating pointer number (C double)

16-// * milliseconds (10^-3 seconds)

17-// * microseconds (10^-6 seconds)

18-// * 100 nanoseconds (10^-7 seconds)

19-// * nanoseconds (10^-9 seconds)

20-// * timeval structure, 1 microsecond resolution (10^-6 seconds)

21-// * timespec structure, 1 nanosecond resolution (10^-9 seconds)

17+// Note that PyTime_t is now specified as int64_t, in nanoseconds.

18+// (If we need to change this, we'll need new public API with new names.)

19+// Previously, PyTime_t was configurable (in theory); some comments and code

20+// might still allude to that.

2221//

2322// Integer overflows are detected and raise OverflowError. Conversion to a

24-// resolution worse than 1 nanosecond is rounded correctly with the requested

25-// rounding mode. There are 4 rounding modes: floor (towards -inf), ceiling

26-// (towards +inf), half even and up (away from zero).

23+// resolution larger than 1 nanosecond is rounded correctly with the requested

24+// rounding mode. Available rounding modes:

2725//

28-// Some functions clamp the result in the range [_PyTime_MIN; _PyTime_MAX], so

29-// the caller doesn't have to handle errors and doesn't need to hold the GIL.

30-// For example, _PyTime_Add(t1, t2) computes t1+t2 and clamp the result on

31-// overflow.

26+// * Round towards minus infinity (-inf). For example, used to read a clock.

27+// * Round towards infinity (+inf). For example, used for timeout to wait "at

28+// least" N seconds.

29+// * Round to nearest with ties going to nearest even integer. For example, used

30+// to round from a Python float.

31+// * Round away from zero. For example, used for timeout.

32+//

33+// Some functions clamp the result in the range [PyTime_MIN; PyTime_MAX]. The

34+// caller doesn't have to handle errors and so doesn't need to hold the GIL to

35+// handle exceptions. For example, _PyTime_Add(t1, t2) computes t1+t2 and

36+// clamps the result on overflow.

3237//

3338// Clocks:

3439//

3540// * System clock

3641// * Monotonic clock

3742// * Performance counter

3843//

39-// Operations like (t * k / q) with integers are implemented in a way to reduce

40-// the risk of integer overflow. Such operation is used to convert a clock

41-// value expressed in ticks with a frequency to _PyTime_t, like

42-// QueryPerformanceCounter() with QueryPerformanceFrequency().

44+// Internally, operations like (t * k / q) with integers are implemented in a

45+// way to reduce the risk of integer overflow. Such operation is used to convert a

46+// clock value expressed in ticks with a frequency to PyTime_t, like

47+// QueryPerformanceCounter() with QueryPerformanceFrequency() on Windows.

48+43494450#ifndefPy_INTERNAL_TIME_H

4551#definePy_INTERNAL_TIME_H

@@ -56,14 +62,7 @@ extern "C" {

5662structtimeval;

5763#endif

586459-// _PyTime_t: Python timestamp with subsecond precision. It can be used to

60-// store a duration, and so indirectly a date (related to another date, like

61-// UNIX epoch).

62-typedefint64_t_PyTime_t;

63-// _PyTime_MIN nanoseconds is around -292.3 years

64-#define_PyTime_MIN INT64_MIN

65-// _PyTime_MAX nanoseconds is around +292.3 years

66-#define_PyTime_MAX INT64_MAX

65+typedefPyTime_t_PyTime_t;

6766#define_SIZEOF_PYTIME_T 8

68676968typedefenum {

@@ -147,7 +146,7 @@ PyAPI_FUNC(_PyTime_t) _PyTime_FromSecondsDouble(double seconds, _PyTime_round_t

147146PyAPI_FUNC(_PyTime_t) _PyTime_FromNanoseconds(_PyTime_tns);

148147149148// Create a timestamp from a number of microseconds.

150-// Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.

149+// Clamp to [PyTime_MIN; PyTime_MAX] on overflow.

151150extern_PyTime_t_PyTime_FromMicrosecondsClamp(_PyTime_tus);

152151153152// Create a timestamp from nanoseconds (Python int).

@@ -169,10 +168,6 @@ PyAPI_FUNC(int) _PyTime_FromMillisecondsObject(_PyTime_t *t,

169168PyObject*obj,

170169_PyTime_round_tround);

171170172-// Convert a timestamp to a number of seconds as a C double.

173-// Export for '_socket' shared extension.

174-PyAPI_FUNC(double) _PyTime_AsSecondsDouble(_PyTime_tt);

175-176171// Convert timestamp to a number of milliseconds (10^-3 seconds).

177172// Export for '_ssl' shared extension.

178173PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_tt,

@@ -183,9 +178,6 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMilliseconds(_PyTime_t t,

183178PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_tt,

184179_PyTime_round_tround);

185180186-// Convert timestamp to a number of nanoseconds (10^-9 seconds).

187-extern_PyTime_t_PyTime_AsNanoseconds(_PyTime_tt);

188-189181#ifdefMS_WINDOWS

190182// Convert timestamp to a number of 100 nanoseconds (10^-7 seconds).

191183extern_PyTime_t_PyTime_As100Nanoseconds(_PyTime_tt,

@@ -250,7 +242,7 @@ PyAPI_FUNC(void) _PyTime_AsTimespec_clamp(_PyTime_t t, struct timespec *ts);

250242#endif

251243252244253-// Compute t1 + t2. Clamp to [_PyTime_MIN; _PyTime_MAX] on overflow.

245+// Compute t1 + t2. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.

254246extern_PyTime_t_PyTime_Add(_PyTime_tt1, _PyTime_tt2);

255247256248// Structure used by time.get_clock_info()

@@ -267,7 +259,8 @@ typedef struct {

267259// On integer overflow, silently ignore the overflow and clamp the clock to

268260// [_PyTime_MIN; _PyTime_MAX].

269261//

270-// Use _PyTime_GetSystemClockWithInfo() to check for failure.

262+// Use _PyTime_GetSystemClockWithInfo or the public PyTime_Time() to check

263+// for failure.

271264// Export for '_random' shared extension.

272265PyAPI_FUNC(_PyTime_t) _PyTime_GetSystemClock(void);

273266@@ -287,7 +280,8 @@ extern int _PyTime_GetSystemClockWithInfo(

287280// On integer overflow, silently ignore the overflow and clamp the clock to

288281// [_PyTime_MIN; _PyTime_MAX].

289282//

290-// Use _PyTime_GetMonotonicClockWithInfo() to check for failure.

283+// Use _PyTime_GetMonotonicClockWithInfo or the public PyTime_Monotonic()

284+// to check for failure.

291285// Export for '_random' shared extension.

292286PyAPI_FUNC(_PyTime_t) _PyTime_GetMonotonicClock(void);

293287@@ -322,10 +316,12 @@ PyAPI_FUNC(int) _PyTime_gmtime(time_t t, struct tm *tm);

322316// On integer overflow, silently ignore the overflow and clamp the clock to

323317// [_PyTime_MIN; _PyTime_MAX].

324318//

325-// Use _PyTime_GetPerfCounterWithInfo() to check for failure.

319+// Use _PyTime_GetPerfCounterWithInfo() or the public PyTime_PerfCounter

320+// to check for failure.

326321// Export for '_lsprof' shared extension.

327322PyAPI_FUNC(_PyTime_t) _PyTime_GetPerfCounter(void);

328323324+329325// Get the performance counter: clock with the highest available resolution to

330326// measure a short duration.

331327//

@@ -336,6 +332,13 @@ extern int _PyTime_GetPerfCounterWithInfo(

336332_PyTime_t*t,

337333_Py_clock_info_t*info);

338334335+// Alias for backward compatibility

336+#define_PyTime_MIN PyTime_MIN

337+#define_PyTime_MAX PyTime_MAX

338+#define_PyTime_AsSecondsDouble PyTime_AsSecondsDouble

339+340+341+// --- _PyDeadline -----------------------------------------------------------

339342340343// Create a deadline.

341344// Pseudo code: _PyTime_GetMonotonicClock() + timeout.