|
5 | 5 | #include "Python.h" |
6 | 6 | #include "pycore_interp.h" // _PyInterpreterState.threads.count |
7 | 7 | #include "pycore_moduleobject.h" // _PyModule_GetState() |
| 8 | +#include "pycore_modsupport.h" // _PyArg_NoKeywords() |
8 | 9 | #include "pycore_pylifecycle.h" |
9 | 10 | #include "pycore_pystate.h" // _PyThreadState_SetCurrent() |
10 | 11 | #include "pycore_sysmodule.h" // _PySys_GetAttr() |
@@ -349,6 +350,27 @@ lock__at_fork_reinit(lockobject *self, PyObject *Py_UNUSED(args)) |
349 | 350 | } |
350 | 351 | #endif /* HAVE_FORK */ |
351 | 352 |
|
| 353 | +static lockobject *newlockobject(PyObject *module); |
| 354 | + |
| 355 | +static PyObject * |
| 356 | +lock_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) |
| 357 | +{ |
| 358 | + // convert to AC? |
| 359 | + if (!_PyArg_NoKeywords("lock", kwargs)) { |
| 360 | + goto error; |
| 361 | + } |
| 362 | + if (!_PyArg_CheckPositional("lock", PyTuple_GET_SIZE(args), 0, 0)) { |
| 363 | + goto error; |
| 364 | + } |
| 365 | + |
| 366 | + PyObject *module = PyType_GetModuleByDef(type, &thread_module); |
| 367 | + assert(module != NULL); |
| 368 | + return (PyObject *)newlockobject(module); |
| 369 | + |
| 370 | +error: |
| 371 | + return NULL; |
| 372 | +} |
| 373 | + |
352 | 374 |
|
353 | 375 | static PyMethodDef lock_methods[] = { |
354 | 376 | {"acquire_lock", _PyCFunction_CAST(lock_PyThread_acquire_lock), |
@@ -398,14 +420,15 @@ static PyType_Slot lock_type_slots[] = { |
398 | 420 | {Py_tp_methods, lock_methods}, |
399 | 421 | {Py_tp_traverse, lock_traverse}, |
400 | 422 | {Py_tp_members, lock_type_members}, |
| 423 | + {Py_tp_new, lock_new}, |
401 | 424 | {0, 0} |
402 | 425 | }; |
403 | 426 |
|
404 | 427 | static PyType_Spec lock_type_spec = { |
405 | 428 | .name = "_thread.lock", |
406 | 429 | .basicsize = sizeof(lockobject), |
407 | 430 | .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
408 | | - Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_IMMUTABLETYPE), |
| 431 | + Py_TPFLAGS_IMMUTABLETYPE), |
409 | 432 | .slots = lock_type_slots, |
410 | 433 | }; |
411 | 434 |
|
@@ -1442,8 +1465,6 @@ A subthread can use this function to interrupt the main thread.\n\ |
1442 | 1465 | Note: the default signal handler for SIGINT raises ``KeyboardInterrupt``." |
1443 | 1466 | ); |
1444 | 1467 |
|
1445 | | -static lockobject *newlockobject(PyObject *module); |
1446 | | - |
1447 | 1468 | static PyObject * |
1448 | 1469 | thread_PyThread_allocate_lock(PyObject *module, PyObject *Py_UNUSED(ignored)) |
1449 | 1470 | { |
@@ -1841,10 +1862,14 @@ thread_module_exec(PyObject *module) |
1841 | 1862 | } |
1842 | 1863 |
|
1843 | 1864 | // Lock |
1844 | | - state->lock_type = (PyTypeObject *)PyType_FromSpec(&lock_type_spec); |
| 1865 | + state->lock_type = (PyTypeObject *)PyType_FromModuleAndSpec(module, &lock_type_spec, NULL); |
1845 | 1866 | if (state->lock_type == NULL) { |
1846 | 1867 | return -1; |
1847 | 1868 | } |
| 1869 | + if (PyModule_AddType(module, state->lock_type) < 0) { |
| 1870 | + return -1; |
| 1871 | + } |
| 1872 | + // Old alias: lock -> LockType |
1848 | 1873 | if (PyDict_SetItemString(d, "LockType", (PyObject *)state->lock_type) < 0) { |
1849 | 1874 | return -1; |
1850 | 1875 | } |
|
0 commit comments