https://github.com/python/cpython/commit/a5b03fa1d71925576892a82f1f12a86f11f69f35
commit: a5b03fa1d71925576892a82f1f12a86f11f69f35
branch: main
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-09-24T18:17:25Z
summary:
gh-155496: Use Argument Clinic for more functions of the _thread module
(GH-155514)
files:
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Modules/_threadmodule.c
M Modules/clinic/_threadmodule.c.h
diff --git a/Include/internal/pycore_global_objects_fini_generated.h
b/Include/internal/pycore_global_objects_fini_generated.h
index 8c8a2d9ea51aef..f3b1fd3ac52680 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -404,6 +404,7 @@ _PyStaticObjects_CheckAll(PyInterpreterState *interp) {
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(ctx), "ctx", 3);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(cwd), "cwd", 3);
_PyStaticObject_CheckUnicodeSingleton((PyObject
*)&_Py_ID(d_parameter_type), "d_parameter_type", 16);
+ _PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(daemon),
"daemon", 6);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(data), "data",
4);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(database),
"database", 8);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(date), "date",
4);
@@ -504,6 +505,7 @@ _PyStaticObjects_CheckAll(PyInterpreterState *interp) {
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(fset), "fset",
4);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(fullerror),
"fullerror", 9);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(func), "func",
4);
+ _PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(function),
"function", 8);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(future),
"future", 6);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(gc), "gc", 2);
_PyStaticObject_CheckUnicodeSingleton((PyObject *)&_Py_ID(generation),
"generation", 10);
diff --git a/Include/internal/pycore_global_strings.h
b/Include/internal/pycore_global_strings.h
index 5b35c53e0aa03b..f6cf449ecc35d8 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -416,6 +416,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(ctx)
STRUCT_FOR_ID(cwd)
STRUCT_FOR_ID(d_parameter_type)
+ STRUCT_FOR_ID(daemon)
STRUCT_FOR_ID(data)
STRUCT_FOR_ID(database)
STRUCT_FOR_ID(date)
@@ -516,6 +517,7 @@ struct _Py_global_strings {
STRUCT_FOR_ID(fset)
STRUCT_FOR_ID(fullerror)
STRUCT_FOR_ID(func)
+ STRUCT_FOR_ID(function)
STRUCT_FOR_ID(future)
STRUCT_FOR_ID(gc)
STRUCT_FOR_ID(generation)
diff --git a/Include/internal/pycore_runtime_init_generated.h
b/Include/internal/pycore_runtime_init_generated.h
index c80925f020186b..e54c9bf97a9476 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -1691,6 +1691,7 @@ extern "C" {
INIT_ID(ctx), \
INIT_ID(cwd), \
INIT_ID(d_parameter_type), \
+ INIT_ID(daemon), \
INIT_ID(data), \
INIT_ID(database), \
INIT_ID(date), \
@@ -1791,6 +1792,7 @@ extern "C" {
INIT_ID(fset), \
INIT_ID(fullerror), \
INIT_ID(func), \
+ INIT_ID(function), \
INIT_ID(future), \
INIT_ID(gc), \
INIT_ID(generation), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h
b/Include/internal/pycore_unicodeobject_generated.h
index a9db3b828d1ef8..e692bd945ac139 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -371,6 +371,7 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
offsetof(struct _Py_global_strings,
identifiers._py_ctx._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_cwd._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_d_parameter_type._ascii.ob_base),
+ offsetof(struct _Py_global_strings,
identifiers._py_daemon._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_data._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_database._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_date._ascii.ob_base),
@@ -471,6 +472,7 @@ _PyUnicode_InitStaticStrings(PyInterpreterState *interp) {
offsetof(struct _Py_global_strings,
identifiers._py_fset._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_fullerror._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_func._ascii.ob_base),
+ offsetof(struct _Py_global_strings,
identifiers._py_function._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_future._ascii.ob_base),
offsetof(struct _Py_global_strings, identifiers._py_gc._ascii.ob_base),
offsetof(struct _Py_global_strings,
identifiers._py_generation._ascii.ob_base),
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index a79ea5728e72d6..058d16f14f290e 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -85,8 +85,9 @@ static PF_SET_THREAD_DESCRIPTION pSetThreadDescription = NULL;
module _thread
class _thread.lock "lockobject *" "clinic_state()->lock_type"
class _thread.RLock "rlockobject *" "clinic_state()->rlock_type"
+class _thread._ThreadHandle "PyObject *" "clinic_state()->thread_handle_type"
[clinic start generated code]*/
-/*[clinic end generated code: output=da39a3ee5e6b4b0d input=c5a0f8c492a0c263]*/
+/*[clinic end generated code: output=da39a3ee5e6b4b0d input=bd4eae07ae18bc2c]*/
#define clinic_state() get_thread_state_by_cls(type)
#include "clinic/_threadmodule.c.h"
@@ -678,43 +679,57 @@ PyThreadHandleObject_repr(PyObject *op)
Py_TYPE(self)->tp_name, ident);
}
+/*[clinic input]
+@getter
+_thread._ThreadHandle.ident
+[clinic start generated code]*/
+
static PyObject *
-PyThreadHandleObject_get_ident(PyObject *op, void *Py_UNUSED(closure))
+_thread__ThreadHandle_ident_get_impl(PyObject *self)
+/*[clinic end generated code: output=66d40aa1a624ac23 input=2b3361e34a6ca79d]*/
{
- PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
- return PyLong_FromUnsignedLongLong(ThreadHandle_ident(self->handle));
+ PyThreadHandleObject *handle = PyThreadHandleObject_CAST(self);
+ return PyLong_FromUnsignedLongLong(ThreadHandle_ident(handle->handle));
}
+/*[clinic input]
+_thread._ThreadHandle.join
+ timeout as timeout_obj: object = None
+ /
+[clinic start generated code]*/
+
static PyObject *
-PyThreadHandleObject_join(PyObject *op, PyObject *args)
+_thread__ThreadHandle_join_impl(PyObject *self, PyObject *timeout_obj)
+/*[clinic end generated code: output=d3a4f0b20c21442e input=b66d17a0f77d6e9c]*/
{
- PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
-
- PyObject *timeout_obj = NULL;
- if (!PyArg_ParseTuple(args, "|O:join", &timeout_obj)) {
- return NULL;
- }
+ PyThreadHandleObject *handle = PyThreadHandleObject_CAST(self);
PyTime_t timeout_ns = -1;
- if (timeout_obj != NULL && timeout_obj != Py_None) {
+ if (timeout_obj != Py_None) {
if (_PyTime_FromSecondsObject(&timeout_ns, timeout_obj,
_PyTime_ROUND_TIMEOUT) < 0) {
return NULL;
}
}
- if (ThreadHandle_join(self->handle, timeout_ns) < 0) {
+ if (ThreadHandle_join(handle->handle, timeout_ns) < 0) {
return NULL;
}
Py_RETURN_NONE;
}
+/*[clinic input]
+_thread._ThreadHandle.is_done
+[clinic start generated code]*/
+
static PyObject *
-PyThreadHandleObject_is_done(PyObject *op, PyObject *Py_UNUSED(dummy))
+_thread__ThreadHandle_is_done_impl(PyObject *self)
+/*[clinic end generated code: output=f5c00923fb61967b input=dd905a1ac7fc2e7c]*/
{
- PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
- if (_PyEvent_IsSet(&self->handle->thread_is_exiting)) {
- if (_PyOnceFlag_CallOnce(&self->handle->once, join_thread,
self->handle) == -1) {
+ PyThreadHandleObject *handle = PyThreadHandleObject_CAST(self);
+ if (_PyEvent_IsSet(&handle->handle->thread_is_exiting)) {
+ if (_PyOnceFlag_CallOnce(&handle->handle->once, join_thread,
+ handle->handle) == -1) {
return NULL;
}
Py_RETURN_TRUE;
@@ -724,25 +739,30 @@ PyThreadHandleObject_is_done(PyObject *op, PyObject
*Py_UNUSED(dummy))
}
}
+/*[clinic input]
+_thread._ThreadHandle._set_done
+[clinic start generated code]*/
+
static PyObject *
-PyThreadHandleObject_set_done(PyObject *op, PyObject *Py_UNUSED(dummy))
+_thread__ThreadHandle__set_done_impl(PyObject *self)
+/*[clinic end generated code: output=709b4d7ca318bb6d input=9f0115db8d84806b]*/
{
- PyThreadHandleObject *self = PyThreadHandleObject_CAST(op);
- if (ThreadHandle_set_done(self->handle) < 0) {
+ PyThreadHandleObject *handle = PyThreadHandleObject_CAST(self);
+ if (ThreadHandle_set_done(handle->handle) < 0) {
return NULL;
}
Py_RETURN_NONE;
}
static PyGetSetDef ThreadHandle_getsetlist[] = {
- {"ident", PyThreadHandleObject_get_ident, NULL, NULL},
+ _THREAD__THREADHANDLE_IDENT_GETSETDEF
{0},
};
static PyMethodDef ThreadHandle_methods[] = {
- {"join", PyThreadHandleObject_join, METH_VARARGS, NULL},
- {"_set_done", PyThreadHandleObject_set_done, METH_NOARGS, NULL},
- {"is_done", PyThreadHandleObject_is_done, METH_NOARGS, NULL},
+ _THREAD__THREADHANDLE_JOIN_METHODDEF
+ _THREAD__THREADHANDLE__SET_DONE_METHODDEF
+ _THREAD__THREADHANDLE_IS_DONE_METHODDEF
{0, 0}
};
@@ -1875,8 +1895,17 @@ clear_locals(PyObject *locals_and_key, PyObject
*dummyweakref)
/* Module functions */
+/*[clinic input]
+_thread.daemon_threads_allowed
+
+Return True if daemon threads are allowed in the current interpreter.
+
+Return False otherwise.
+[clinic start generated code]*/
+
static PyObject *
-thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
+_thread_daemon_threads_allowed_impl(PyObject *module)
+/*[clinic end generated code: output=c82b3b9490c7e11e input=f94150f9e14b7d0c]*/
{
PyInterpreterState *interp = _PyInterpreterState_GET();
if (interp->feature_flags & Py_RTFLAGS_DAEMON_THREADS) {
@@ -1887,13 +1916,6 @@ thread_daemon_threads_allowed(PyObject *module, PyObject
*Py_UNUSED(ignored))
}
}
-PyDoc_STRVAR(daemon_threads_allowed_doc,
-"daemon_threads_allowed($module, /)\n\
---\n\
-\n\
-Return True if daemon threads are allowed in the current interpreter,\n\
-and False otherwise.\n");
-
static int
do_start_new_thread(thread_module_state *state, PyObject *func, PyObject *args,
PyObject *kwargs, ThreadHandle *handle, int daemon)
@@ -1927,31 +1949,36 @@ do_start_new_thread(thread_module_state *state,
PyObject *func, PyObject *args,
return 0;
}
+/*[clinic input]
+_thread.start_new_thread
+
+ function as func: object
+ args: object(subclass_of='&PyTuple_Type')
+ kwargs: object(subclass_of='&PyDict_Type', c_default="NULL") = {}
+ /
+
+Start a new thread and return its identifier.
+
+The thread will call the function with positional arguments from the
+tuple args and keyword arguments taken from the optional dictionary
+kwargs. The thread exits when the function returns; the return value
+is ignored. The thread will also exit when the function raises an
+unhandled exception; a stack trace will be printed unless the exception
+is SystemExit.
+[clinic start generated code]*/
+
static PyObject *
-thread_PyThread_start_new_thread(PyObject *module, PyObject *fargs)
+_thread_start_new_thread_impl(PyObject *module, PyObject *func,
+ PyObject *args, PyObject *kwargs)
+/*[clinic end generated code: output=0c27eb61b7a7152b input=b85f6b3301d30719]*/
{
- PyObject *func, *args, *kwargs = NULL;
thread_module_state *state = get_thread_state(module);
- if (!PyArg_UnpackTuple(fargs, "start_new_thread", 2, 3,
- &func, &args, &kwargs))
- return NULL;
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError,
"first arg must be callable");
return NULL;
}
- if (!PyTuple_Check(args)) {
- PyErr_SetString(PyExc_TypeError,
- "2nd arg must be a tuple");
- return NULL;
- }
- if (kwargs != NULL && !PyDict_Check(kwargs)) {
- PyErr_SetString(PyExc_TypeError,
- "optional 3rd arg must be a dictionary");
- return NULL;
- }
-
if (PySys_Audit("_thread.start_new_thread", "OOO",
func, args, kwargs ? kwargs : Py_None) < 0) {
return NULL;
@@ -1973,39 +2000,36 @@ thread_PyThread_start_new_thread(PyObject *module,
PyObject *fargs)
return PyLong_FromUnsignedLongLong(ident);
}
-PyDoc_STRVAR(start_new_thread_doc,
-"start_new_thread($module, function, args, kwargs={}, /)\n\
---\n\
-\n\
-Start a new thread and return its identifier.\n\
-\n\
-The thread will call the function with positional arguments from the\n\
-tuple args and keyword arguments taken from the optional dictionary\n\
-kwargs. The thread exits when the function returns; the return value\n\
-is ignored. The thread will also exit when the function raises an\n\
-unhandled exception; a stack trace will be printed unless the exception\n\
-is SystemExit.");
-
PyDoc_STRVAR(start_new_doc,
"start_new($module, function, args, kwargs={}, /)\n\
--\n\
\n\
An obsolete synonym of start_new_thread().");
+/*[clinic input]
+_thread.start_joinable_thread
+
+ function as func: object
+ handle as hobj: object = None
+ daemon: bool = True
+
+*For internal use only*: start a new thread.
+
+Like start_new_thread(), this starts a new thread calling the given
+function. Unlike start_new_thread(), this returns a handle object with
+methods to join or detach the given thread.
+This function is not for third-party code, please use the `threading`
+module instead. During finalization the runtime will not wait for the
+thread to exit if daemon is True. If handle is provided it must be a
+newly created thread._ThreadHandle instance.
+[clinic start generated code]*/
+
static PyObject *
-thread_PyThread_start_joinable_thread(PyObject *module, PyObject *fargs,
- PyObject *fkwargs)
+_thread_start_joinable_thread_impl(PyObject *module, PyObject *func,
+ PyObject *hobj, int daemon)
+/*[clinic end generated code: output=58691769e60620cf input=e17b3aebc087952a]*/
{
- static char *keywords[] = {"function", "handle", "daemon", NULL};
- PyObject *func = NULL;
- int daemon = 1;
thread_module_state *state = get_thread_state(module);
- PyObject *hobj = NULL;
- if (!PyArg_ParseTupleAndKeywords(fargs, fkwargs,
- "O|Op:start_joinable_thread", keywords,
- &func, &hobj, &daemon)) {
- return NULL;
- }
if (!PyCallable_Check(func)) {
PyErr_SetString(PyExc_TypeError,
@@ -2013,10 +2037,7 @@ thread_PyThread_start_joinable_thread(PyObject *module,
PyObject *fargs,
return NULL;
}
- if (hobj == NULL) {
- hobj = Py_None;
- }
- else if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
+ if (hobj != Py_None && !Py_IS_TYPE(hobj, state->thread_handle_type)) {
PyErr_SetString(PyExc_TypeError, "'handle' must be a _ThreadHandle");
return NULL;
}
@@ -2050,48 +2071,49 @@ thread_PyThread_start_joinable_thread(PyObject *module,
PyObject *fargs,
return (PyObject *) hobj;
}
-PyDoc_STRVAR(start_joinable_doc,
-"start_joinable_thread($module, /, function, handle=None, daemon=True)\n\
---\n\
-\n\
-*For internal use only*: start a new thread.\n\
-\n\
-Like start_new_thread(), this starts a new thread calling the given
function.\n\
-Unlike start_new_thread(), this returns a handle object with methods to join\n\
-or detach the given thread.\n\
-This function is not for third-party code, please use the\n\
-`threading` module instead. During finalization the runtime will not wait
for\n\
-the thread to exit if daemon is True. If handle is provided it must be a\n\
-newly created thread._ThreadHandle instance.");
+/*[clinic input]
+_thread.exit
+
+Raise SystemExit.
+
+It will cause the current thread to exit silently unless the exception
+is caught.
+[clinic start generated code]*/
static PyObject *
-thread_PyThread_exit_thread(PyObject *self, PyObject *Py_UNUSED(ignored))
+_thread_exit_impl(PyObject *module)
+/*[clinic end generated code: output=b03924346e743f4c input=1f3dc5da8ad48c70]*/
{
PyErr_SetNone(PyExc_SystemExit);
return NULL;
}
-PyDoc_STRVAR(exit_doc,
-"exit($module, /)\n\
---\n\
-\n\
-This is synonymous to ``raise SystemExit''. It will cause the current\n\
-thread to exit silently unless the exception is caught.");
-
PyDoc_STRVAR(exit_thread_doc,
"exit_thread($module, /)\n\
--\n\
\n\
An obsolete synonym of exit().");
+/*[clinic input]
+_thread.interrupt_main
+
+ signum: int(c_default="SIGINT") = signal.SIGINT
+ /
+
+Simulate the arrival of the given signal in the main thread.
+
+The corresponding signal handler will be executed.
+If *signum* is omitted, SIGINT is assumed.
+A subthread can use this function to interrupt the main thread.
+
+Note: the default signal handler for SIGINT raises
+``KeyboardInterrupt``.
+[clinic start generated code]*/
+
static PyObject *
-thread_PyThread_interrupt_main(PyObject *self, PyObject *args)
+_thread_interrupt_main_impl(PyObject *module, int signum)
+/*[clinic end generated code: output=fdafa7261ceb26e9 input=a8cf392f3a7f2a84]*/
{
- int signum = SIGINT;
- if (!PyArg_ParseTuple(args, "|i:signum", &signum)) {
- return NULL;
- }
-
if (PyErr_SetInterruptEx(signum)) {
PyErr_SetString(PyExc_ValueError, "signal number out of range");
return NULL;
@@ -2099,40 +2121,44 @@ thread_PyThread_interrupt_main(PyObject *self, PyObject
*args)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(interrupt_doc,
-"interrupt_main($module, signum=signal.SIGINT, /)\n\
---\n\
-\n\
-Simulate the arrival of the given signal in the main thread,\n\
-where the corresponding signal handler will be executed.\n\
-If *signum* is omitted, SIGINT is assumed.\n\
-A subthread can use this function to interrupt the main thread.\n\
-\n\
-Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``."
-);
+/*[clinic input]
+_thread.allocate_lock
+
+Create a new lock object.
+
+See help(type(threading.Lock())) for information about locks.
+[clinic start generated code]*/
static PyObject *
-thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
+_thread_allocate_lock_impl(PyObject *module)
+/*[clinic end generated code: output=884a4be6cb9ca731 input=49f5b1f966361bb6]*/
{
thread_module_state *state = get_thread_state(module);
return lock_new_impl(state->lock_type);
}
-PyDoc_STRVAR(allocate_lock_doc,
-"allocate_lock($module, /)\n\
---\n\
-\n\
-Create a new lock object. See help(type(threading.Lock())) for\n\
-information about locks.");
-
PyDoc_STRVAR(allocate_doc,
"allocate($module, /)\n\
--\n\
\n\
An obsolete synonym of allocate_lock().");
+/*[clinic input]
+_thread.get_ident
+
+Return a non-zero integer that uniquely identifies the current thread.
+
+It is unique amongst other threads that exist simultaneously.
+This may be used to identify per-thread resources.
+Even though on some platforms threads identities may appear to be
+allocated consecutive numbers starting at 1, this behavior should not
+be relied upon, and the number should be seen purely as a magic cookie.
+A thread's identity may be reused for another thread after it exits.
+[clinic start generated code]*/
+
static PyObject *
-thread_get_ident(PyObject *self, PyObject *Py_UNUSED(ignored))
+_thread_get_ident_impl(PyObject *module)
+/*[clinic end generated code: output=8c3f9d8aa938b332 input=08faef37d1fd9e67]*/
{
PyThread_ident_t ident = PyThread_get_thread_ident_ex();
if (ident == PYTHREAD_INVALID_THREAD_ID) {
@@ -2142,64 +2168,79 @@ thread_get_ident(PyObject *self, PyObject
*Py_UNUSED(ignored))
return PyLong_FromUnsignedLongLong(ident);
}
-PyDoc_STRVAR(get_ident_doc,
-"get_ident($module, /)\n\
---\n\
-\n\
-Return a non-zero integer that uniquely identifies the current thread\n\
-amongst other threads that exist simultaneously.\n\
-This may be used to identify per-thread resources.\n\
-Even though on some platforms threads identities may appear to be\n\
-allocated consecutive numbers starting at 1, this behavior should not\n\
-be relied upon, and the number should be seen purely as a magic cookie.\n\
-A thread's identity may be reused for another thread after it exits.");
-
#ifdef PY_HAVE_THREAD_NATIVE_ID
+/*[clinic input]
+_thread.get_native_id
+
+Return a non-negative integer identifying the thread.
+
+It is reported by the OS (kernel). This may be used to uniquely
+identify a particular thread within a system.
+[clinic start generated code]*/
+
static PyObject *
-thread_get_native_id(PyObject *self, PyObject *Py_UNUSED(ignored))
+_thread_get_native_id_impl(PyObject *module)
+/*[clinic end generated code: output=d69767224b4ba922 input=454af91013e4f747]*/
{
unsigned long native_id = PyThread_get_thread_native_id();
return PyLong_FromUnsignedLong(native_id);
}
-PyDoc_STRVAR(get_native_id_doc,
-"get_native_id($module, /)\n\
---\n\
-\n\
-Return a non-negative integer identifying the thread as reported\n\
-by the OS (kernel). This may be used to uniquely identify a\n\
-particular thread within a system.");
#endif
+/*[clinic input]
+_thread._count
+
+Return the number of currently running Python threads.
+
+The main thread is excluded. The returned number comprises all threads
+created through `start_new_thread()` as well as `threading.Thread`, and
+not yet finished.
+
+This function is meant for internal and specialized purposes only.
+In most applications `threading.enumerate()` should be used instead.
+[clinic start generated code]*/
+
static PyObject *
-thread__count(PyObject *self, PyObject *Py_UNUSED(ignored))
+_thread__count_impl(PyObject *module)
+/*[clinic end generated code: output=4cd03377c3e8521d input=bbd340043d174d48]*/
{
PyInterpreterState *interp = _PyInterpreterState_GET();
return PyLong_FromSsize_t(_Py_atomic_load_ssize(&interp->threads.count));
}
-PyDoc_STRVAR(_count_doc,
-"_count($module, /)\n\
---\n\
-\n\
-Return the number of currently running Python threads, excluding\n\
-the main thread. The returned number comprises all threads created\n\
-through `start_new_thread()` as well as `threading.Thread`, and not\n\
-yet finished.\n\
-\n\
-This function is meant for internal and specialized purposes only.\n\
-In most applications `threading.enumerate()` should be used instead.");
+/*[clinic input]
+_thread.stack_size
+
+ size as new_size: Py_ssize_t = 0
+ /
+
+Return the thread stack size used when creating new threads.
+
+The optional size argument specifies the stack size (in bytes) to be
+used for subsequently created threads, and must be 0 (use platform or
+configured default) or a positive integer value of at least 32,768 (32
+KiB). If changing the thread stack size is unsupported, a ThreadError
+exception is raised. If the specified size is invalid, a ValueError
+exception is raised, and the stack size is unmodified. 32 KiB
+currently is the minimum supported stack size value to guarantee
+sufficient stack space for the interpreter itself.
+
+Note that some systems may have particular restrictions on values for
+the stack size, such as requiring a minimum stack size larger than 32
+KiB or requiring allocation in multiples of the system memory page size
+- platform documentation should be referred to for more information
+(4 KiB pages are common; using multiples of 4096 for the stack size is
+the suggested approach in the absence of more specific information).
+[clinic start generated code]*/
static PyObject *
-thread_stack_size(PyObject *self, PyObject *args)
+_thread_stack_size_impl(PyObject *module, Py_ssize_t new_size)
+/*[clinic end generated code: output=cc7ba71bd35afc30 input=3249feb8ed2350f8]*/
{
size_t old_size;
- Py_ssize_t new_size = 0;
int rc;
- if (!PyArg_ParseTuple(args, "|n:stack_size", &new_size))
- return NULL;
-
Py_ssize_t min_size = _PyOS_MIN_STACK_SIZE + SYSTEM_PAGE_SIZE;
if (new_size != 0 && new_size < min_size) {
PyErr_Format(PyExc_ValueError,
@@ -2225,27 +2266,6 @@ thread_stack_size(PyObject *self, PyObject *args)
return PyLong_FromSsize_t((Py_ssize_t) old_size);
}
-PyDoc_STRVAR(stack_size_doc,
-"stack_size($module, size=0, /)\n\
---\n\
-\n\
-Return the thread stack size used when creating new threads. The\n\
-optional size argument specifies the stack size (in bytes) to be used\n\
-for subsequently created threads, and must be 0 (use platform or\n\
-configured default) or a positive integer value of at least 32,768 (32k).\n\
-If changing the thread stack size is unsupported, a ThreadError\n\
-exception is raised. If the specified size is invalid, a ValueError\n\
-exception is raised, and the stack size is unmodified. 32k bytes\n\
- currently the minimum supported stack size value to guarantee\n\
-sufficient stack space for the interpreter itself.\n\
-\n\
-Note that some platforms may have particular restrictions on values for\n\
-the stack size, such as requiring a minimum stack size larger than 32 KiB or\n\
-requiring allocation in multiples of the system memory page size\n\
-- platform documentation should be referred to for more information\n\
-(4 KiB pages are common; using multiples of 4096 for the stack size is\n\
-the suggested approach in the absence of more specific information).");
-
static int
thread_excepthook_file(PyObject *file, PyObject *exc_type, PyObject *exc_value,
PyObject *exc_traceback, PyObject *thread)
@@ -2324,8 +2344,18 @@ static PyStructSequence_Desc ExceptHookArgs_desc = {
};
+/*[clinic input]
+_thread._excepthook
+
+ args: object
+ /
+
+Handle uncaught Thread.run() exception.
+[clinic start generated code]*/
+
static PyObject *
-thread_excepthook(PyObject *module, PyObject *args)
+_thread__excepthook(PyObject *module, PyObject *args)
+/*[clinic end generated code: output=cadc54a3be0e6007 input=5ae2316c400a3497]*/
{
thread_module_state *state = get_thread_state(module);
@@ -2381,30 +2411,32 @@ thread_excepthook(PyObject *module, PyObject *args)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(excepthook_doc,
-"_excepthook($module, args, /)\n\
---\n\
-\n\
-Handle uncaught Thread.run() exception.");
+/*[clinic input]
+_thread._is_main_interpreter
+
+Return True if the current interpreter is the main Python interpreter.
+[clinic start generated code]*/
static PyObject *
-thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored))
+_thread__is_main_interpreter_impl(PyObject *module)
+/*[clinic end generated code: output=7dd82e1728339adc input=cc1eb00fd4598915]*/
{
PyInterpreterState *interp = _PyInterpreterState_GET();
return PyBool_FromLong(_Py_IsMainInterpreter(interp));
}
-PyDoc_STRVAR(thread__is_main_interpreter_doc,
-"_is_main_interpreter($module, /)\n\
---\n\
-\n\
-Return True if the current interpreter is the main Python interpreter.");
+/*[clinic input]
+_thread._shutdown
+
+Wait for all non-daemon threads (other than the calling thread) to stop.
+[clinic start generated code]*/
static PyObject *
-thread_shutdown(PyObject *self, PyObject *args)
+_thread__shutdown_impl(PyObject *module)
+/*[clinic end generated code: output=a19afe92bddc1824 input=bcaeaceb3a6fa590]*/
{
PyThread_ident_t ident = PyThread_get_thread_ident_ex();
- thread_module_state *state = get_thread_state(self);
+ thread_module_state *state = get_thread_state(module);
for (;;) {
ThreadHandle *handle = NULL;
@@ -2440,14 +2472,21 @@ thread_shutdown(PyObject *self, PyObject *args)
Py_RETURN_NONE;
}
-PyDoc_STRVAR(shutdown_doc,
-"_shutdown($module, /)\n\
---\n\
-\n\
-Wait for all non-daemon threads (other than the calling thread) to stop.");
+/*[clinic input]
+_thread._make_thread_handle
+
+ ident as identobj: object
+ /
+
+Internal only.
+
+Make a thread handle for threads not spawned by the _thread or
+threading module.
+[clinic start generated code]*/
static PyObject *
-thread__make_thread_handle(PyObject *module, PyObject *identobj)
+_thread__make_thread_handle(PyObject *module, PyObject *identobj)
+/*[clinic end generated code: output=afa56c40a7e1c394 input=57bb20ebf5825dd1]*/
{
thread_module_state *state = get_thread_state(module);
if (!PyLong_Check(identobj)) {
@@ -2470,26 +2509,22 @@ thread__make_thread_handle(PyObject *module, PyObject
*identobj)
return (PyObject*) hobj;
}
-PyDoc_STRVAR(thread__make_thread_handle_doc,
-"_make_thread_handle($module, ident, /)\n\
---\n\
-\n\
-Internal only. Make a thread handle for threads not spawned\n\
-by the _thread or threading module.");
+/*[clinic input]
+_thread._get_main_thread_ident
+
+Internal only.
+
+Return a non-zero integer that uniquely identifies the main thread of
+the main interpreter.
+[clinic start generated code]*/
static PyObject *
-thread__get_main_thread_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
+_thread__get_main_thread_ident_impl(PyObject *module)
+/*[clinic end generated code: output=01aa07c5553458bf input=feea25c7039ba4b5]*/
{
return PyLong_FromUnsignedLongLong(_PyRuntime.main_thread);
}
-PyDoc_STRVAR(thread__get_main_thread_ident_doc,
-"_get_main_thread_ident($module, /)\n\
---\n\
-\n\
-Internal only. Return a non-zero integer that uniquely identifies the main
thread\n\
-of the main interpreter.");
-
#if defined(__OpenBSD__)
/* pthread_*_np functions, especially pthread_{get,set}_name_np().
pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
@@ -2649,44 +2684,29 @@ _thread_set_name_impl(PyObject *module, PyObject
*name_obj)
static PyMethodDef thread_methods[] = {
- {"start_new_thread", thread_PyThread_start_new_thread,
- METH_VARARGS, start_new_thread_doc},
- {"start_new", thread_PyThread_start_new_thread,
- METH_VARARGS, start_new_doc},
- {"start_joinable_thread",
_PyCFunction_CAST(thread_PyThread_start_joinable_thread),
- METH_VARARGS | METH_KEYWORDS, start_joinable_doc},
- {"daemon_threads_allowed", thread_daemon_threads_allowed,
- METH_NOARGS, daemon_threads_allowed_doc},
- {"allocate_lock", thread_PyThread_allocate_lock,
- METH_NOARGS, allocate_lock_doc},
- {"allocate", thread_PyThread_allocate_lock,
+ _THREAD_START_NEW_THREAD_METHODDEF
+ {"start_new", _PyCFunction_CAST(_thread_start_new_thread),
+ METH_FASTCALL, start_new_doc},
+ _THREAD_START_JOINABLE_THREAD_METHODDEF
+ _THREAD_DAEMON_THREADS_ALLOWED_METHODDEF
+ _THREAD_ALLOCATE_LOCK_METHODDEF
+ {"allocate", _thread_allocate_lock,
METH_NOARGS, allocate_doc},
- {"exit_thread", thread_PyThread_exit_thread,
+ {"exit_thread", _thread_exit,
METH_NOARGS, exit_thread_doc},
- {"exit", thread_PyThread_exit_thread,
- METH_NOARGS, exit_doc},
- {"interrupt_main", thread_PyThread_interrupt_main,
- METH_VARARGS, interrupt_doc},
- {"get_ident", thread_get_ident,
- METH_NOARGS, get_ident_doc},
+ _THREAD_EXIT_METHODDEF
+ _THREAD_INTERRUPT_MAIN_METHODDEF
+ _THREAD_GET_IDENT_METHODDEF
#ifdef PY_HAVE_THREAD_NATIVE_ID
- {"get_native_id", thread_get_native_id,
- METH_NOARGS, get_native_id_doc},
+ _THREAD_GET_NATIVE_ID_METHODDEF
#endif
- {"_count", thread__count,
- METH_NOARGS, _count_doc},
- {"stack_size", thread_stack_size,
- METH_VARARGS, stack_size_doc},
- {"_excepthook", thread_excepthook,
- METH_O, excepthook_doc},
- {"_is_main_interpreter", thread__is_main_interpreter,
- METH_NOARGS, thread__is_main_interpreter_doc},
- {"_shutdown", thread_shutdown,
- METH_NOARGS, shutdown_doc},
- {"_make_thread_handle", thread__make_thread_handle,
- METH_O, thread__make_thread_handle_doc},
- {"_get_main_thread_ident", thread__get_main_thread_ident,
- METH_NOARGS, thread__get_main_thread_ident_doc},
+ _THREAD__COUNT_METHODDEF
+ _THREAD_STACK_SIZE_METHODDEF
+ _THREAD__EXCEPTHOOK_METHODDEF
+ _THREAD__IS_MAIN_INTERPRETER_METHODDEF
+ _THREAD__SHUTDOWN_METHODDEF
+ _THREAD__MAKE_THREAD_HANDLE_METHODDEF
+ _THREAD__GET_MAIN_THREAD_IDENT_METHODDEF
_THREAD_SET_NAME_METHODDEF
_THREAD__GET_NAME_METHODDEF
{NULL, NULL} /* sentinel */
diff --git a/Modules/clinic/_threadmodule.c.h b/Modules/clinic/_threadmodule.c.h
index 926bea8e1e419a..090fdee8f6593e 100644
--- a/Modules/clinic/_threadmodule.c.h
+++ b/Modules/clinic/_threadmodule.c.h
@@ -6,7 +6,82 @@ preserve
# include "pycore_gc.h" // PyGC_Head
# include "pycore_runtime.h" // _Py_ID()
#endif
-#include "pycore_modsupport.h" // _PyArg_UnpackKeywords()
+#include "pycore_abstract.h" // _PyNumber_Index()
+#include "pycore_modsupport.h" // _PyArg_CheckPositional()
+
+static PyObject *
+_thread__ThreadHandle_ident_get_impl(PyObject *self);
+
+static PyObject *
+_thread__ThreadHandle_ident_get(PyObject *self, void *Py_UNUSED(context))
+{
+ return _thread__ThreadHandle_ident_get_impl(self);
+}
+
+PyDoc_STRVAR(_thread__ThreadHandle_join__doc__,
+"join($self, timeout=None, /)\n"
+"--\n"
+"\n");
+
+#define _THREAD__THREADHANDLE_JOIN_METHODDEF \
+ {"join", _PyCFunction_CAST(_thread__ThreadHandle_join), METH_FASTCALL,
_thread__ThreadHandle_join__doc__},
+
+static PyObject *
+_thread__ThreadHandle_join_impl(PyObject *self, PyObject *timeout_obj);
+
+static PyObject *
+_thread__ThreadHandle_join(PyObject *self, PyObject *const *args, Py_ssize_t
nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *timeout_obj = Py_None;
+
+ if (!_PyArg_CheckPositional("join", nargs, 0, 1)) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional;
+ }
+ timeout_obj = args[0];
+skip_optional:
+ return_value = _thread__ThreadHandle_join_impl(self, timeout_obj);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_thread__ThreadHandle_is_done__doc__,
+"is_done($self, /)\n"
+"--\n"
+"\n");
+
+#define _THREAD__THREADHANDLE_IS_DONE_METHODDEF \
+ {"is_done", (PyCFunction)_thread__ThreadHandle_is_done, METH_NOARGS,
_thread__ThreadHandle_is_done__doc__},
+
+static PyObject *
+_thread__ThreadHandle_is_done_impl(PyObject *self);
+
+static PyObject *
+_thread__ThreadHandle_is_done(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__ThreadHandle_is_done_impl(self);
+}
+
+PyDoc_STRVAR(_thread__ThreadHandle__set_done__doc__,
+"_set_done($self, /)\n"
+"--\n"
+"\n");
+
+#define _THREAD__THREADHANDLE__SET_DONE_METHODDEF \
+ {"_set_done", (PyCFunction)_thread__ThreadHandle__set_done, METH_NOARGS,
_thread__ThreadHandle__set_done__doc__},
+
+static PyObject *
+_thread__ThreadHandle__set_done_impl(PyObject *self);
+
+static PyObject *
+_thread__ThreadHandle__set_done(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__ThreadHandle__set_done_impl(self);
+}
PyDoc_STRVAR(_thread_lock_acquire__doc__,
"acquire($self, /, blocking=True, timeout=-1)\n"
@@ -637,6 +712,457 @@ _thread_RLock__at_fork_reinit(PyObject *self, PyObject
*Py_UNUSED(ignored))
#endif /* defined(HAVE_FORK) */
+PyDoc_STRVAR(_thread_daemon_threads_allowed__doc__,
+"daemon_threads_allowed($module, /)\n"
+"--\n"
+"\n"
+"Return True if daemon threads are allowed in the current interpreter.\n"
+"\n"
+"Return False otherwise.");
+
+#define _THREAD_DAEMON_THREADS_ALLOWED_METHODDEF \
+ {"daemon_threads_allowed", (PyCFunction)_thread_daemon_threads_allowed,
METH_NOARGS, _thread_daemon_threads_allowed__doc__},
+
+static PyObject *
+_thread_daemon_threads_allowed_impl(PyObject *module);
+
+static PyObject *
+_thread_daemon_threads_allowed(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread_daemon_threads_allowed_impl(module);
+}
+
+PyDoc_STRVAR(_thread_start_new_thread__doc__,
+"start_new_thread($module, function, args, kwargs={}, /)\n"
+"--\n"
+"\n"
+"Start a new thread and return its identifier.\n"
+"\n"
+"The thread will call the function with positional arguments from the\n"
+"tuple args and keyword arguments taken from the optional dictionary\n"
+"kwargs. The thread exits when the function returns; the return value\n"
+"is ignored. The thread will also exit when the function raises an\n"
+"unhandled exception; a stack trace will be printed unless the exception\n"
+"is SystemExit.");
+
+#define _THREAD_START_NEW_THREAD_METHODDEF \
+ {"start_new_thread", _PyCFunction_CAST(_thread_start_new_thread),
METH_FASTCALL, _thread_start_new_thread__doc__},
+
+static PyObject *
+_thread_start_new_thread_impl(PyObject *module, PyObject *func,
+ PyObject *args, PyObject *kwargs);
+
+static PyObject *
+_thread_start_new_thread(PyObject *module, PyObject *const *args, Py_ssize_t
nargs)
+{
+ PyObject *return_value = NULL;
+ PyObject *func;
+ PyObject *__clinic_args;
+ PyObject *__clinic_kwargs = NULL;
+
+ if (!_PyArg_CheckPositional("start_new_thread", nargs, 2, 3)) {
+ goto exit;
+ }
+ func = args[0];
+ if (!PyTuple_Check(args[1])) {
+ _PyArg_BadArgument("start_new_thread", "argument 2", "tuple", args[1]);
+ goto exit;
+ }
+ __clinic_args = args[1];
+ if (nargs < 3) {
+ goto skip_optional;
+ }
+ if (!PyDict_Check(args[2])) {
+ _PyArg_BadArgument("start_new_thread", "argument 3", "dict", args[2]);
+ goto exit;
+ }
+ __clinic_kwargs = args[2];
+skip_optional:
+ return_value = _thread_start_new_thread_impl(module, func, __clinic_args,
__clinic_kwargs);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_thread_start_joinable_thread__doc__,
+"start_joinable_thread($module, /, function, handle=None, daemon=True)\n"
+"--\n"
+"\n"
+"*For internal use only*: start a new thread.\n"
+"\n"
+"Like start_new_thread(), this starts a new thread calling the given\n"
+"function. Unlike start_new_thread(), this returns a handle object with\n"
+"methods to join or detach the given thread.\n"
+"This function is not for third-party code, please use the `threading`\n"
+"module instead. During finalization the runtime will not wait for the\n"
+"thread to exit if daemon is True. If handle is provided it must be a\n"
+"newly created thread._ThreadHandle instance.");
+
+#define _THREAD_START_JOINABLE_THREAD_METHODDEF \
+ {"start_joinable_thread",
_PyCFunction_CAST(_thread_start_joinable_thread), METH_FASTCALL|METH_KEYWORDS,
_thread_start_joinable_thread__doc__},
+
+static PyObject *
+_thread_start_joinable_thread_impl(PyObject *module, PyObject *func,
+ PyObject *hobj, int daemon);
+
+static PyObject *
+_thread_start_joinable_thread(PyObject *module, PyObject *const *args,
Py_ssize_t nargs, PyObject *kwnames)
+{
+ PyObject *return_value = NULL;
+ #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
+
+ #define NUM_KEYWORDS 3
+ static struct {
+ PyGC_Head _this_is_not_used;
+ PyObject_VAR_HEAD
+ Py_hash_t ob_hash;
+ PyObject *ob_item[NUM_KEYWORDS];
+ } _kwtuple = {
+ .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
+ .ob_hash = -1,
+ .ob_item = { &_Py_ID(function), &_Py_ID(handle), &_Py_ID(daemon), },
+ };
+ #undef NUM_KEYWORDS
+ #define KWTUPLE (&_kwtuple.ob_base.ob_base)
+
+ #else // !Py_BUILD_CORE
+ # define KWTUPLE NULL
+ #endif // !Py_BUILD_CORE
+
+ static const char * const _keywords[] = {"function", "handle", "daemon",
NULL};
+ static _PyArg_Parser _parser = {
+ .keywords = _keywords,
+ .fname = "start_joinable_thread",
+ .kwtuple = KWTUPLE,
+ };
+ #undef KWTUPLE
+ PyObject *argsbuf[3];
+ Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) -
1;
+ PyObject *func;
+ PyObject *hobj = Py_None;
+ int daemon = 1;
+
+ args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser,
+ /*minpos*/ 1, /*maxpos*/ 3, /*minkw*/ 0, /*varpos*/ 0, argsbuf);
+ if (!args) {
+ goto exit;
+ }
+ func = args[0];
+ if (!noptargs) {
+ goto skip_optional_pos;
+ }
+ if (args[1]) {
+ hobj = args[1];
+ if (!--noptargs) {
+ goto skip_optional_pos;
+ }
+ }
+ daemon = PyObject_IsTrue(args[2]);
+ if (daemon < 0) {
+ goto exit;
+ }
+skip_optional_pos:
+ return_value = _thread_start_joinable_thread_impl(module, func, hobj,
daemon);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_thread_exit__doc__,
+"exit($module, /)\n"
+"--\n"
+"\n"
+"Raise SystemExit.\n"
+"\n"
+"It will cause the current thread to exit silently unless the exception\n"
+"is caught.");
+
+#define _THREAD_EXIT_METHODDEF \
+ {"exit", (PyCFunction)_thread_exit, METH_NOARGS, _thread_exit__doc__},
+
+static PyObject *
+_thread_exit_impl(PyObject *module);
+
+static PyObject *
+_thread_exit(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread_exit_impl(module);
+}
+
+PyDoc_STRVAR(_thread_interrupt_main__doc__,
+"interrupt_main($module, signum=signal.SIGINT, /)\n"
+"--\n"
+"\n"
+"Simulate the arrival of the given signal in the main thread.\n"
+"\n"
+"The corresponding signal handler will be executed.\n"
+"If *signum* is omitted, SIGINT is assumed.\n"
+"A subthread can use this function to interrupt the main thread.\n"
+"\n"
+"Note: the default signal handler for SIGINT raises\n"
+"``KeyboardInterrupt``.");
+
+#define _THREAD_INTERRUPT_MAIN_METHODDEF \
+ {"interrupt_main", _PyCFunction_CAST(_thread_interrupt_main),
METH_FASTCALL, _thread_interrupt_main__doc__},
+
+static PyObject *
+_thread_interrupt_main_impl(PyObject *module, int signum);
+
+static PyObject *
+_thread_interrupt_main(PyObject *module, PyObject *const *args, Py_ssize_t
nargs)
+{
+ PyObject *return_value = NULL;
+ int signum = SIGINT;
+
+ if (!_PyArg_CheckPositional("interrupt_main", nargs, 0, 1)) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional;
+ }
+ signum = PyLong_AsInt(args[0]);
+ if (signum == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+skip_optional:
+ return_value = _thread_interrupt_main_impl(module, signum);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_thread_allocate_lock__doc__,
+"allocate_lock($module, /)\n"
+"--\n"
+"\n"
+"Create a new lock object.\n"
+"\n"
+"See help(type(threading.Lock())) for information about locks.");
+
+#define _THREAD_ALLOCATE_LOCK_METHODDEF \
+ {"allocate_lock", (PyCFunction)_thread_allocate_lock, METH_NOARGS,
_thread_allocate_lock__doc__},
+
+static PyObject *
+_thread_allocate_lock_impl(PyObject *module);
+
+static PyObject *
+_thread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread_allocate_lock_impl(module);
+}
+
+PyDoc_STRVAR(_thread_get_ident__doc__,
+"get_ident($module, /)\n"
+"--\n"
+"\n"
+"Return a non-zero integer that uniquely identifies the current thread.\n"
+"\n"
+"It is unique amongst other threads that exist simultaneously.\n"
+"This may be used to identify per-thread resources.\n"
+"Even though on some platforms threads identities may appear to be\n"
+"allocated consecutive numbers starting at 1, this behavior should not\n"
+"be relied upon, and the number should be seen purely as a magic cookie.\n"
+"A thread\'s identity may be reused for another thread after it exits.");
+
+#define _THREAD_GET_IDENT_METHODDEF \
+ {"get_ident", (PyCFunction)_thread_get_ident, METH_NOARGS,
_thread_get_ident__doc__},
+
+static PyObject *
+_thread_get_ident_impl(PyObject *module);
+
+static PyObject *
+_thread_get_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread_get_ident_impl(module);
+}
+
+#if defined(PY_HAVE_THREAD_NATIVE_ID)
+
+PyDoc_STRVAR(_thread_get_native_id__doc__,
+"get_native_id($module, /)\n"
+"--\n"
+"\n"
+"Return a non-negative integer identifying the thread.\n"
+"\n"
+"It is reported by the OS (kernel). This may be used to uniquely\n"
+"identify a particular thread within a system.");
+
+#define _THREAD_GET_NATIVE_ID_METHODDEF \
+ {"get_native_id", (PyCFunction)_thread_get_native_id, METH_NOARGS,
_thread_get_native_id__doc__},
+
+static PyObject *
+_thread_get_native_id_impl(PyObject *module);
+
+static PyObject *
+_thread_get_native_id(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread_get_native_id_impl(module);
+}
+
+#endif /* defined(PY_HAVE_THREAD_NATIVE_ID) */
+
+PyDoc_STRVAR(_thread__count__doc__,
+"_count($module, /)\n"
+"--\n"
+"\n"
+"Return the number of currently running Python threads.\n"
+"\n"
+"The main thread is excluded. The returned number comprises all threads\n"
+"created through `start_new_thread()` as well as `threading.Thread`, and\n"
+"not yet finished.\n"
+"\n"
+"This function is meant for internal and specialized purposes only.\n"
+"In most applications `threading.enumerate()` should be used instead.");
+
+#define _THREAD__COUNT_METHODDEF \
+ {"_count", (PyCFunction)_thread__count, METH_NOARGS,
_thread__count__doc__},
+
+static PyObject *
+_thread__count_impl(PyObject *module);
+
+static PyObject *
+_thread__count(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__count_impl(module);
+}
+
+PyDoc_STRVAR(_thread_stack_size__doc__,
+"stack_size($module, size=0, /)\n"
+"--\n"
+"\n"
+"Return the thread stack size used when creating new threads.\n"
+"\n"
+"The optional size argument specifies the stack size (in bytes) to be\n"
+"used for subsequently created threads, and must be 0 (use platform or\n"
+"configured default) or a positive integer value of at least 32,768 (32\n"
+"KiB). If changing the thread stack size is unsupported, a ThreadError\n"
+"exception is raised. If the specified size is invalid, a ValueError\n"
+"exception is raised, and the stack size is unmodified. 32 KiB\n"
+"currently is the minimum supported stack size value to guarantee\n"
+"sufficient stack space for the interpreter itself.\n"
+"\n"
+"Note that some systems may have particular restrictions on values for\n"
+"the stack size, such as requiring a minimum stack size larger than 32\n"
+"KiB or requiring allocation in multiples of the system memory page size\n"
+"- platform documentation should be referred to for more information\n"
+"(4 KiB pages are common; using multiples of 4096 for the stack size is\n"
+"the suggested approach in the absence of more specific information).");
+
+#define _THREAD_STACK_SIZE_METHODDEF \
+ {"stack_size", _PyCFunction_CAST(_thread_stack_size), METH_FASTCALL,
_thread_stack_size__doc__},
+
+static PyObject *
+_thread_stack_size_impl(PyObject *module, Py_ssize_t new_size);
+
+static PyObject *
+_thread_stack_size(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
+{
+ PyObject *return_value = NULL;
+ Py_ssize_t new_size = 0;
+
+ if (!_PyArg_CheckPositional("stack_size", nargs, 0, 1)) {
+ goto exit;
+ }
+ if (nargs < 1) {
+ goto skip_optional;
+ }
+ {
+ Py_ssize_t ival = -1;
+ PyObject *iobj = _PyNumber_Index(args[0]);
+ if (iobj != NULL) {
+ ival = PyLong_AsSsize_t(iobj);
+ Py_DECREF(iobj);
+ }
+ if (ival == -1 && PyErr_Occurred()) {
+ goto exit;
+ }
+ new_size = ival;
+ }
+skip_optional:
+ return_value = _thread_stack_size_impl(module, new_size);
+
+exit:
+ return return_value;
+}
+
+PyDoc_STRVAR(_thread__excepthook__doc__,
+"_excepthook($module, args, /)\n"
+"--\n"
+"\n"
+"Handle uncaught Thread.run() exception.");
+
+#define _THREAD__EXCEPTHOOK_METHODDEF \
+ {"_excepthook", (PyCFunction)_thread__excepthook, METH_O,
_thread__excepthook__doc__},
+
+PyDoc_STRVAR(_thread__is_main_interpreter__doc__,
+"_is_main_interpreter($module, /)\n"
+"--\n"
+"\n"
+"Return True if the current interpreter is the main Python interpreter.");
+
+#define _THREAD__IS_MAIN_INTERPRETER_METHODDEF \
+ {"_is_main_interpreter", (PyCFunction)_thread__is_main_interpreter,
METH_NOARGS, _thread__is_main_interpreter__doc__},
+
+static PyObject *
+_thread__is_main_interpreter_impl(PyObject *module);
+
+static PyObject *
+_thread__is_main_interpreter(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__is_main_interpreter_impl(module);
+}
+
+PyDoc_STRVAR(_thread__shutdown__doc__,
+"_shutdown($module, /)\n"
+"--\n"
+"\n"
+"Wait for all non-daemon threads (other than the calling thread) to stop.");
+
+#define _THREAD__SHUTDOWN_METHODDEF \
+ {"_shutdown", (PyCFunction)_thread__shutdown, METH_NOARGS,
_thread__shutdown__doc__},
+
+static PyObject *
+_thread__shutdown_impl(PyObject *module);
+
+static PyObject *
+_thread__shutdown(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__shutdown_impl(module);
+}
+
+PyDoc_STRVAR(_thread__make_thread_handle__doc__,
+"_make_thread_handle($module, ident, /)\n"
+"--\n"
+"\n"
+"Internal only.\n"
+"\n"
+"Make a thread handle for threads not spawned by the _thread or\n"
+"threading module.");
+
+#define _THREAD__MAKE_THREAD_HANDLE_METHODDEF \
+ {"_make_thread_handle", (PyCFunction)_thread__make_thread_handle, METH_O,
_thread__make_thread_handle__doc__},
+
+PyDoc_STRVAR(_thread__get_main_thread_ident__doc__,
+"_get_main_thread_ident($module, /)\n"
+"--\n"
+"\n"
+"Internal only.\n"
+"\n"
+"Return a non-zero integer that uniquely identifies the main thread of\n"
+"the main interpreter.");
+
+#define _THREAD__GET_MAIN_THREAD_IDENT_METHODDEF \
+ {"_get_main_thread_ident", (PyCFunction)_thread__get_main_thread_ident,
METH_NOARGS, _thread__get_main_thread_ident__doc__},
+
+static PyObject *
+_thread__get_main_thread_ident_impl(PyObject *module);
+
+static PyObject *
+_thread__get_main_thread_ident(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return _thread__get_main_thread_ident_impl(module);
+}
+
#if (defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP) ||
defined(MS_WINDOWS))
PyDoc_STRVAR(_thread__get_name__doc__,
@@ -733,6 +1259,10 @@ _thread_set_name(PyObject *module, PyObject *const *args,
Py_ssize_t nargs, PyOb
#define _THREAD_RLOCK__AT_FORK_REINIT_METHODDEF
#endif /* !defined(_THREAD_RLOCK__AT_FORK_REINIT_METHODDEF) */
+#ifndef _THREAD_GET_NATIVE_ID_METHODDEF
+ #define _THREAD_GET_NATIVE_ID_METHODDEF
+#endif /* !defined(_THREAD_GET_NATIVE_ID_METHODDEF) */
+
#ifndef _THREAD__GET_NAME_METHODDEF
#define _THREAD__GET_NAME_METHODDEF
#endif /* !defined(_THREAD__GET_NAME_METHODDEF) */
@@ -740,4 +1270,6 @@ _thread_set_name(PyObject *module, PyObject *const *args,
Py_ssize_t nargs, PyOb
#ifndef _THREAD_SET_NAME_METHODDEF
#define _THREAD_SET_NAME_METHODDEF
#endif /* !defined(_THREAD_SET_NAME_METHODDEF) */
-/*[clinic end generated code: output=0f1707cbafc0e8f2 input=a9049054013a1b77]*/
+#define _THREAD__THREADHANDLE_IDENT_GETSETDEF {"ident",
(getter)_thread__ThreadHandle_ident_get, (setter)NULL, NULL},
+
+/*[clinic end generated code: output=3bfc76a318c6579d input=a9049054013a1b77]*/
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]