mirror of https://github.com/python/cpython
Close #10278: Add clock_getres(), clock_gettime() and CLOCK_xxx constants to
the time module. time.clock_gettime(time.CLOCK_MONOTONIC) provides a monotonic clock
This commit is contained in:
parent
92b958420e
commit
e0be423297
|
@ -136,6 +136,54 @@ The module defines the following functions and data items:
|
||||||
microsecond.
|
microsecond.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: clock_getres(clk_id)
|
||||||
|
|
||||||
|
Return the resolution (precision) of the specified clock *clk_id*.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. function:: clock_gettime(clk_id)
|
||||||
|
|
||||||
|
Return the time of the specified clock *clk_id*.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. data:: CLOCK_REALTIME
|
||||||
|
|
||||||
|
System-wide real-time clock. Setting this clock requires appropriate
|
||||||
|
privileges.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. data:: CLOCK_MONOTONIC
|
||||||
|
|
||||||
|
Clock that cannot be set and represents monotonic time since some
|
||||||
|
unspecified starting point.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. data:: CLOCK_MONOTONIC_RAW
|
||||||
|
|
||||||
|
Similar to :data:`CLOCK_MONOTONIC`, but provides access to a raw
|
||||||
|
hardware-based time that is not subject to NTP adjustments.
|
||||||
|
|
||||||
|
Availability: Linux 2.6.28 or later.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. data:: CLOCK_PROCESS_CPUTIME_ID
|
||||||
|
|
||||||
|
High-resolution per-process timer from the CPU.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. data:: CLOCK_THREAD_CPUTIME_ID
|
||||||
|
|
||||||
|
Thread-specific CPU-time clock.
|
||||||
|
|
||||||
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
|
||||||
.. function:: ctime([secs])
|
.. function:: ctime([secs])
|
||||||
|
|
||||||
Convert a time expressed in seconds since the epoch to a string representing
|
Convert a time expressed in seconds since the epoch to a string representing
|
||||||
|
|
|
@ -272,6 +272,16 @@ New module: :mod:`faulthandler`.
|
||||||
* :envvar:`PYTHONFAULTHANDLER`
|
* :envvar:`PYTHONFAULTHANDLER`
|
||||||
* :option:`-X` ``faulthandler``
|
* :option:`-X` ``faulthandler``
|
||||||
|
|
||||||
|
time
|
||||||
|
----
|
||||||
|
|
||||||
|
* The :mod:`time` module has new :func:`~time.clock_getres` and
|
||||||
|
:func:`~time.clock_gettime` functions and ``CLOCK_xxx`` constants.
|
||||||
|
:func:`~time.clock_gettime` can be used with :data:`time.CLOCK_MONOTONIC` to
|
||||||
|
get a monotonic clock.
|
||||||
|
|
||||||
|
(Contributed by Victor Stinner in :issue:`10278`)
|
||||||
|
|
||||||
|
|
||||||
ftplib
|
ftplib
|
||||||
------
|
------
|
||||||
|
|
|
@ -20,6 +20,27 @@ class TimeTestCase(unittest.TestCase):
|
||||||
def test_clock(self):
|
def test_clock(self):
|
||||||
time.clock()
|
time.clock()
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
|
||||||
|
'need time.clock_gettime()')
|
||||||
|
def test_clock_realtime(self):
|
||||||
|
time.clock_gettime(time.CLOCK_REALTIME)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
|
||||||
|
'need time.clock_gettime()')
|
||||||
|
@unittest.skipUnless(hasattr(time, 'CLOCK_MONOTONIC'),
|
||||||
|
'need time.CLOCK_MONOTONIC')
|
||||||
|
def test_clock_monotonic(self):
|
||||||
|
a = time.clock_gettime(time.CLOCK_MONOTONIC)
|
||||||
|
b = time.clock_gettime(time.CLOCK_MONOTONIC)
|
||||||
|
self.assertLessEqual(a, b)
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(time, 'clock_getres'),
|
||||||
|
'need time.clock_getres()')
|
||||||
|
def test_clock_getres(self):
|
||||||
|
res = time.clock_getres(time.CLOCK_REALTIME)
|
||||||
|
self.assertGreater(res, 0.0)
|
||||||
|
self.assertLessEqual(res, 1.0)
|
||||||
|
|
||||||
def test_conversions(self):
|
def test_conversions(self):
|
||||||
self.assertEqual(time.ctime(self.t),
|
self.assertEqual(time.ctime(self.t),
|
||||||
time.asctime(time.localtime(self.t)))
|
time.asctime(time.localtime(self.t)))
|
||||||
|
|
|
@ -341,6 +341,10 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #10278: Add clock_getres(), clock_gettime() and CLOCK_xxx constants to
|
||||||
|
the time module. time.clock_gettime(time.CLOCK_MONOTONIC) provides a
|
||||||
|
monotonic clock
|
||||||
|
|
||||||
- Issue #10332: multiprocessing: fix a race condition when a Pool is closed
|
- Issue #10332: multiprocessing: fix a race condition when a Pool is closed
|
||||||
before all tasks have completed.
|
before all tasks have completed.
|
||||||
|
|
||||||
|
|
|
@ -135,6 +135,54 @@ the first call to clock(). This has as much precision as the system\n\
|
||||||
records.");
|
records.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
static PyObject *
|
||||||
|
time_clock_gettime(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
clockid_t clk_id;
|
||||||
|
struct timespec tp;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "i:clock_gettime", &clk_id))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = clock_gettime((clockid_t)clk_id, &tp);
|
||||||
|
if (ret != 0)
|
||||||
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
|
|
||||||
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(clock_gettime_doc,
|
||||||
|
"clock_gettime(clk_id) -> floating point number\n\
|
||||||
|
\n\
|
||||||
|
Return the time of the specified clock clk_id.");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOCK_GETRES
|
||||||
|
static PyObject *
|
||||||
|
time_clock_getres(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
clockid_t clk_id;
|
||||||
|
struct timespec tp;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "i:clock_getres", &clk_id))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = clock_getres((clockid_t)clk_id, &tp);
|
||||||
|
if (ret != 0)
|
||||||
|
PyErr_SetFromErrno(PyExc_IOError);
|
||||||
|
|
||||||
|
return PyFloat_FromDouble(tp.tv_sec + tp.tv_nsec * 1e-9);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(clock_getres_doc,
|
||||||
|
"clock_getres(clk_id) -> floating point number\n\
|
||||||
|
\n\
|
||||||
|
Return the resolution (precision) of the specified clock clk_id.");
|
||||||
|
#endif
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
time_sleep(PyObject *self, PyObject *args)
|
time_sleep(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
|
@ -786,6 +834,24 @@ PyInit_timezone(PyObject *m) {
|
||||||
Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
|
Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
|
||||||
#endif /* __CYGWIN__ */
|
#endif /* __CYGWIN__ */
|
||||||
#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
|
#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
|
||||||
|
|
||||||
|
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETRES)
|
||||||
|
#ifdef CLOCK_REALTIME
|
||||||
|
PyModule_AddIntMacro(m, CLOCK_REALTIME);
|
||||||
|
#endif
|
||||||
|
#ifdef CLOCK_MONOTONIC
|
||||||
|
PyModule_AddIntMacro(m, CLOCK_MONOTONIC);
|
||||||
|
#endif
|
||||||
|
#ifdef CLOCK_MONOTONIC_RAW
|
||||||
|
PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW);
|
||||||
|
#endif
|
||||||
|
#ifdef CLOCK_PROCESS_CPUTIME_ID
|
||||||
|
PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID);
|
||||||
|
#endif
|
||||||
|
#ifdef CLOCK_THREAD_CPUTIME_ID
|
||||||
|
PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
|
||||||
|
#endif
|
||||||
|
#endif /* HAVE_CLOCK_GETTIME */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -793,6 +859,12 @@ static PyMethodDef time_methods[] = {
|
||||||
{"time", time_time, METH_NOARGS, time_doc},
|
{"time", time_time, METH_NOARGS, time_doc},
|
||||||
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
#if (defined(MS_WINDOWS) && !defined(__BORLANDC__)) || defined(HAVE_CLOCK)
|
||||||
{"clock", time_clock, METH_NOARGS, clock_doc},
|
{"clock", time_clock, METH_NOARGS, clock_doc},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME
|
||||||
|
{"clock_gettime", time_clock_gettime, METH_VARARGS, clock_gettime_doc},
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_CLOCK_GETRES
|
||||||
|
{"clock_getres", time_clock_getres, METH_VARARGS, clock_getres_doc},
|
||||||
#endif
|
#endif
|
||||||
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
|
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
|
||||||
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
|
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
|
||||||
|
|
14
configure.in
14
configure.in
|
@ -2856,6 +2856,20 @@ AC_CHECK_FUNCS(gettimeofday,
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(clock_gettime, [], [
|
||||||
|
AC_CHECK_LIB(rt, clock_gettime, [
|
||||||
|
AC_DEFINE(HAVE_CLOCK_GETTIME, 1)
|
||||||
|
AC_DEFINE(TIMEMODULE_LIB, [rt],
|
||||||
|
[Library needed by timemodule.c: librt may be needed for clock_gettime()])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_CHECK_FUNCS(clock_getres, [], [
|
||||||
|
AC_CHECK_LIB(rt, clock_getres, [
|
||||||
|
AC_DEFINE(HAVE_CLOCK_GETRES, 1)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING(for major, minor, and makedev)
|
AC_MSG_CHECKING(for major, minor, and makedev)
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#if defined(MAJOR_IN_MKDEV)
|
#if defined(MAJOR_IN_MKDEV)
|
||||||
|
|
|
@ -110,6 +110,12 @@
|
||||||
/* Define to 1 if you have the `clock' function. */
|
/* Define to 1 if you have the `clock' function. */
|
||||||
#undef HAVE_CLOCK
|
#undef HAVE_CLOCK
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `clock_getres' function. */
|
||||||
|
#undef HAVE_CLOCK_GETRES
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
|
#undef HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
/* Define if the C compiler supports computed gotos. */
|
/* Define if the C compiler supports computed gotos. */
|
||||||
#undef HAVE_COMPUTED_GOTOS
|
#undef HAVE_COMPUTED_GOTOS
|
||||||
|
|
||||||
|
@ -1199,6 +1205,9 @@
|
||||||
/* Define if tanh(-0.) is -0., or if platform doesn't have signed zeros */
|
/* Define if tanh(-0.) is -0., or if platform doesn't have signed zeros */
|
||||||
#undef TANH_PRESERVES_ZERO_SIGN
|
#undef TANH_PRESERVES_ZERO_SIGN
|
||||||
|
|
||||||
|
/* Library needed by timemodule.c: librt may be needed for clock_gettime() */
|
||||||
|
#undef TIMEMODULE_LIB
|
||||||
|
|
||||||
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
|
||||||
#undef TIME_WITH_SYS_TIME
|
#undef TIME_WITH_SYS_TIME
|
||||||
|
|
||||||
|
|
12
setup.py
12
setup.py
|
@ -504,11 +504,17 @@ class PyBuildExt(build_ext):
|
||||||
exts.append( Extension('math', ['mathmodule.c', '_math.c'],
|
exts.append( Extension('math', ['mathmodule.c', '_math.c'],
|
||||||
depends=['_math.h'],
|
depends=['_math.h'],
|
||||||
libraries=math_libs) )
|
libraries=math_libs) )
|
||||||
|
|
||||||
|
# time libraries: librt may be needed for clock_gettime()
|
||||||
|
time_libs = []
|
||||||
|
lib = sysconfig.get_config_var('TIMEMODULE_LIB')
|
||||||
|
if lib:
|
||||||
|
time_libs.append(lib)
|
||||||
|
|
||||||
# time operations and variables
|
# time operations and variables
|
||||||
exts.append( Extension('time', ['timemodule.c', '_time.c'],
|
exts.append( Extension('time', ['timemodule.c', '_time.c'],
|
||||||
libraries=math_libs) )
|
libraries=time_libs) )
|
||||||
exts.append( Extension('_datetime', ['_datetimemodule.c', '_time.c'],
|
exts.append( Extension('_datetime', ['_datetimemodule.c', '_time.c']) )
|
||||||
libraries=math_libs) )
|
|
||||||
# random number generator implemented in C
|
# random number generator implemented in C
|
||||||
exts.append( Extension("_random", ["_randommodule.c"]) )
|
exts.append( Extension("_random", ["_randommodule.c"]) )
|
||||||
# bisect
|
# bisect
|
||||||
|
|
Loading…
Reference in New Issue