From 071eca3f5c55f127f754bd5575123ec94d8c3eaa Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 15 Mar 2012 01:17:09 +0100 Subject: [PATCH] Issue #10278: Add an optional strict argument to time.steady(), False by default --- Doc/library/time.rst | 7 +++++- Lib/test/test_time.py | 10 ++++++++ Modules/timemodule.c | 58 ++++++++++++++++++++++++++++++------------- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst index 63d45fd0402..fcee5513893 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -226,7 +226,7 @@ The module defines the following functions and data items: The earliest date for which it can generate a time is platform-dependent. -.. function:: steady() +.. function:: steady(strict=False) .. index:: single: benchmarking @@ -236,6 +236,11 @@ The module defines the following functions and data items: adjusted. The reference point of the returned value is undefined so only the difference of consecutive calls is valid. + If available, a monotonic clock is used. By default, if *strict* is False, + the function falls back to another clock if the monotonic clock failed or is + not available. If *strict* is True, raise an :exc:`OSError` on error or + :exc:`NotImplementedError` if no monotonic clock is available. + .. versionadded:: 3.3 diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py index 2baf066820b..28d018afe7a 100644 --- a/Lib/test/test_time.py +++ b/Lib/test/test_time.py @@ -340,6 +340,16 @@ class TimeTestCase(unittest.TestCase): self.assertGreater(t2, t1) self.assertAlmostEqual(dt, 0.1, delta=0.2) + def test_steady_strict(self): + try: + t1 = time.steady(strict=True) + except OSError as err: + self.skipTest("the monotonic clock failed: %s" % err) + except NotImplementedError: + self.skipTest("no monotonic clock available") + t2 = time.steady(strict=True) + self.assertGreaterEqual(t2, t1) + def test_localtime_failure(self): # Issue #13847: check for localtime() failure invalid_time_t = None diff --git a/Modules/timemodule.c b/Modules/timemodule.c index c7efce681a6..e6e1ff400ef 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -45,18 +45,12 @@ /* Forward declarations */ static int floatsleep(double); -static double floattime(void); +static PyObject* floattime(void); static PyObject * time_time(PyObject *self, PyObject *unused) { - double secs; - secs = floattime(); - if (secs == 0.0) { - PyErr_SetFromErrno(PyExc_IOError); - return NULL; - } - return PyFloat_FromDouble(secs); + return floattime(); } PyDoc_STRVAR(time_doc, @@ -768,11 +762,11 @@ the local timezone used by methods such as localtime, but this behaviour\n\ should not be relied on."); #endif /* HAVE_WORKING_TZSET */ -static PyObject * -time_steady(PyObject *self, PyObject *unused) +static PyObject* +steady_clock(int strict) { #if defined(MS_WINDOWS) && !defined(__BORLANDC__) - return win32_clock(1); + return win32_clock(!strict); #elif defined(__APPLE__) uint64_t time = mach_absolute_time(); double secs; @@ -806,14 +800,37 @@ time_steady(PyObject *self, PyObject *unused) if (Py_ARRAY_LENGTH(clk_ids) <= clk_index) clk_index = -1; } - return time_time(self, NULL); + if (strict) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return floattime(); #else - return time_time(self, NULL); + if (strict) { + PyErr_SetString(PyExc_NotImplementedError, + "no steady clock available on your platform"); + return NULL; + } + return floattime(); #endif } +static PyObject * +time_steady(PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *kwlist[] = {"strict", NULL}; + int strict = 0; + + if (!PyArg_ParseTupleAndKeywords( + args, kwargs, "|i:steady", kwlist, + &strict)) + return NULL; + + return steady_clock(strict); +} + PyDoc_STRVAR(steady_doc, -"steady() -> float\n\ +"steady(strict=False) -> float\n\ \n\ Return the current time as a floating point number expressed in seconds.\n\ This clock advances at a steady rate relative to real time and it may not\n\ @@ -949,7 +966,8 @@ static PyMethodDef time_methods[] = { #ifdef HAVE_MKTIME {"mktime", time_mktime, METH_O, mktime_doc}, #endif - {"steady", time_steady, METH_NOARGS, steady_doc}, + {"steady", (PyCFunction)time_steady, METH_VARARGS|METH_KEYWORDS, + steady_doc}, #ifdef HAVE_STRFTIME {"strftime", time_strftime, METH_VARARGS, strftime_doc}, #endif @@ -1041,12 +1059,18 @@ PyInit_time(void) return m; } -static double +static PyObject* floattime(void) { _PyTime_timeval t; + double secs; _PyTime_gettimeofday(&t); - return (double)t.tv_sec + t.tv_usec*0.000001; + secs = (double)t.tv_sec + t.tv_usec*0.000001; + if (secs == 0.0) { + PyErr_SetFromErrno(PyExc_OSError); + return NULL; + } + return PyFloat_FromDouble(secs); }