Skip to content

Commit 32f1556

Browse files
Factor out PyThread_ParseTimeoutArg().
1 parent fb3b9e1 commit 32f1556

File tree

4 files changed

+47
-5
lines changed

4 files changed

+47
-5
lines changed

Include/cpython/pythread.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ PyAPI_DATA(const long long) PY_TIMEOUT_MAX;
2929
#endif
3030

3131

32+
PyAPI_FUNC(int) PyThread_ParseTimeoutArg(
33+
PyObject *arg,
34+
int blocking,
35+
PY_TIMEOUT_T *timeout);
36+
3237
/* Helper to acquire an interruptible lock with a timeout. If the lock acquire
3338
* is interrupted, signal handlers are run, and if they raise an exception,
3439
* PY_LOCK_INTR is returned. Otherwise, PY_LOCK_ACQUIRED or PY_LOCK_FAILURE

Modules/_queuemodule.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ _queue_SimpleQueue_get_impl(simplequeueobject *self, PyTypeObject *cls,
214214
PY_TIMEOUT_T microseconds;
215215
PyThreadState *tstate = PyThreadState_Get();
216216

217+
// XXX Use PyThread_ParseTimeoutArg().
218+
217219
if (block == 0) {
218220
/* Non-blocking */
219221
microseconds = 0;

Modules/_threadmodule.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,15 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
8888
char *kwlist[] = {"blocking", "timeout", NULL};
8989
int blocking = 1;
9090
PyObject *timeout_obj = NULL;
91-
const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
92-
93-
*timeout = unset_timeout ;
94-
9591
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|pO:acquire", kwlist,
9692
&blocking, &timeout_obj))
9793
return -1;
9894

95+
// XXX Use PyThread_ParseTimeoutArg().
96+
97+
const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
98+
*timeout = unset_timeout;
99+
99100
if (timeout_obj
100101
&& _PyTime_FromSecondsObject(timeout,
101102
timeout_obj, _PyTime_ROUND_TIMEOUT) < 0)
@@ -108,7 +109,7 @@ lock_acquire_parse_args(PyObject *args, PyObject *kwds,
108109
}
109110
if (*timeout < 0 && *timeout != unset_timeout) {
110111
PyErr_SetString(PyExc_ValueError,
111-
"timeout value must be positive");
112+
"timeout value must be a non-negative number");
112113
return -1;
113114
}
114115
if (!blocking)

Python/thread.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,40 @@ PyThread_set_stacksize(size_t size)
9393
}
9494

9595

96+
int
97+
PyThread_ParseTimeoutArg(PyObject *arg, int blocking, PY_TIMEOUT_T *timeout_p)
98+
{
99+
const _PyTime_t unset_timeout = _PyTime_FromSeconds(-1);
100+
if (arg == NULL || arg == Py_None) {
101+
*timeout_p = blocking ? unset_timeout : 0;
102+
return 0;
103+
}
104+
if (!blocking) {
105+
PyErr_SetString(PyExc_ValueError,
106+
"can't specify a timeout for a non-blocking call");
107+
return -1;
108+
}
109+
110+
_PyTime_t timeout;
111+
if (_PyTime_FromSecondsObject(&timeout, arg, _PyTime_ROUND_TIMEOUT) < 0) {
112+
return -1;
113+
}
114+
if (timeout < 0) {
115+
PyErr_SetString(PyExc_ValueError,
116+
"timeout value must be a non-negative number");
117+
return -1;
118+
}
119+
120+
if (_PyTime_AsMicroseconds(timeout,
121+
_PyTime_ROUND_TIMEOUT) > PY_TIMEOUT_MAX) {
122+
PyErr_SetString(PyExc_OverflowError,
123+
"timeout value is too large");
124+
return -1;
125+
}
126+
*timeout_p = timeout;
127+
return 0;
128+
}
129+
96130
PyLockStatus
97131
PyThread_acquire_lock_timed_with_retries(PyThread_type_lock lock,
98132
PY_TIMEOUT_T timeout)

0 commit comments

Comments
 (0)