Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaa3716f

Browse files
committed
gh-103743: Add PyUnstable_Object_GC_NewWithExtraData (#103743)
1 parentaf53046 commitaa3716f

File tree

7 files changed

+140
-1
lines changed

7 files changed

+140
-1
lines changed

‎Doc/c-api/gcsupport.rst‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ rules:
6565
Analogous to:c:func:`PyObject_NewVar` but for container objects with the
6666
:const:`Py_TPFLAGS_HAVE_GC` flag set.
6767
68+
..c:function:: TYPE*PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)
69+
70+
Analogous to:c:func:`PyObject_GC_New` but for container objects that
71+
have additional data at the end of the object not managed by Python.
72+
73+
..warning::
74+
The function is marked as unstable because the final mechanism
75+
for reserving extra data after an instance is not yet decided.
76+
Once:pep:`697` is implemented, the mechanism described there can
77+
be used to reserve the extra data.
78+
79+
..versionadded::3.12
80+
6881
6982
..c:function:: TYPE*PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)
7083

‎Include/objimpl.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ PyAPI_FUNC(PyVarObject *) PyObject_InitVar(PyVarObject *,
131131
PyAPI_FUNC(PyObject*)_PyObject_New(PyTypeObject*);
132132
PyAPI_FUNC(PyVarObject*)_PyObject_NewVar(PyTypeObject*,Py_ssize_t);
133133

134+
#if !defined(Py_LIMITED_API)
135+
PyAPI_FUNC(PyObject*)PyUnstable_Object_GC_NewWithExtraData(PyTypeObject*,size_t);
136+
#endif
137+
134138
#definePyObject_New(type,typeobj) ((type *)_PyObject_New(typeobj))
135139

136140
// Alias to PyObject_New(). In Python 3.8, PyObject_NEW() called directly

‎Lib/test/test_capi/test_misc.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,6 +1043,20 @@ class dictsub(dict): ... # dict subclasses must work
10431043
self.assertEqual(_testcapi.function_get_kw_defaults(some),None)
10441044
self.assertEqual(some.__kwdefaults__,None)
10451045

1046+
deftest_unstable_gc_new_with_extra_data(self):
1047+
classData(_testcapi.ObjExtraData):
1048+
__slots__= ('x','y')
1049+
1050+
d=Data()
1051+
d.x=10
1052+
d.y=20
1053+
d.extra=30
1054+
self.assertEqual(d.x,10)
1055+
self.assertEqual(d.y,20)
1056+
self.assertEqual(d.extra,30)
1057+
deld.extra
1058+
self.assertIsNone(d.extra)
1059+
10461060

10471061
classTestPendingCalls(unittest.TestCase):
10481062

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add ``PyUnstable_Object_GC_NewWithExtraData`` function that can be used to
2+
allocate additional memory after an object for data not managed by Python.

‎Modules/_testcapimodule.c‎

Lines changed: 94 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3343,7 +3343,7 @@ test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
33433343
}
33443344
state.target=obj;
33453345
state.found=0;
3346-
3346+
33473347
PyUnstable_GC_VisitObjects(gc_visit_callback_basic,&state);
33483348
Py_DECREF(obj);
33493349
if (!state.found) {
@@ -3380,6 +3380,94 @@ test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self),
33803380
Py_RETURN_NONE;
33813381
}
33823382

3383+
typedefstruct {
3384+
PyObject_HEAD
3385+
}ObjExtraData;
3386+
3387+
staticPyObject*
3388+
obj_extra_data_new(PyTypeObject*type,PyObject*args,PyObject*kwds)
3389+
{
3390+
size_textra_size=sizeof(PyObject*);
3391+
PyObject*obj=PyUnstable_Object_GC_NewWithExtraData(type,extra_size);
3392+
if (obj==NULL)
3393+
returnPyErr_NoMemory();
3394+
memset(obj,'\0',type->tp_basicsize+extra_size);
3395+
PyObject_Init(obj,type);
3396+
PyObject_GC_Track(obj);
3397+
returnobj;
3398+
}
3399+
3400+
staticPyObject**
3401+
obj_extra_data_get_extra_storage(PyObject*self)
3402+
{
3403+
return (PyObject**)((char*)self+Py_TYPE(self)->tp_basicsize);
3404+
}
3405+
3406+
staticPyObject*
3407+
obj_extra_data_get(PyObject*self,void*Py_UNUSED(ignored))
3408+
{
3409+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3410+
PyObject*value=*extra_storage;
3411+
if (!value)
3412+
Py_RETURN_NONE;
3413+
Py_INCREF(value);
3414+
returnvalue;
3415+
}
3416+
3417+
staticint
3418+
obj_extra_data_set(PyObject*self,PyObject*newval,void*Py_UNUSED(ignored))
3419+
{
3420+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3421+
Py_CLEAR(*extra_storage);
3422+
if (newval) {
3423+
Py_INCREF(newval);
3424+
*extra_storage=newval;
3425+
}
3426+
return0;
3427+
}
3428+
3429+
staticPyGetSetDefobj_extra_data_getset[]= {
3430+
{"extra", (getter)obj_extra_data_get, (setter)obj_extra_data_set,NULL},
3431+
};
3432+
3433+
staticint
3434+
obj_extra_data_traverse(PyObject*self,visitprocvisit,void*arg)
3435+
{
3436+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3437+
PyObject*value=*extra_storage;
3438+
Py_VISIT(value);
3439+
return0;
3440+
}
3441+
3442+
staticint
3443+
obj_extra_data_clear(PyObject*self)
3444+
{
3445+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3446+
Py_CLEAR(*extra_storage);
3447+
return0;
3448+
}
3449+
3450+
staticvoid
3451+
obj_extra_data_dealloc(PyObject*self)
3452+
{
3453+
PyObject_GC_UnTrack(self);
3454+
obj_extra_data_clear(self);
3455+
Py_TYPE(self)->tp_free(self);
3456+
}
3457+
3458+
staticPyTypeObjectObjExtraData_Type= {
3459+
PyVarObject_HEAD_INIT(NULL,0)
3460+
"obj_with_extra_data",
3461+
sizeof(ObjExtraData),
3462+
0,
3463+
.tp_getset=obj_extra_data_getset,
3464+
.tp_dealloc=obj_extra_data_dealloc,
3465+
.tp_flags=Py_TPFLAGS_DEFAULT |Py_TPFLAGS_BASETYPE |Py_TPFLAGS_HAVE_GC,
3466+
.tp_traverse= (traverseproc)obj_extra_data_traverse,
3467+
.tp_clear= (inquiry)obj_extra_data_clear,
3468+
.tp_new=obj_extra_data_new,
3469+
.tp_free=PyObject_GC_Del,
3470+
};
33833471

33843472
structatexit_data {
33853473
intcalled;
@@ -4103,6 +4191,11 @@ PyInit__testcapi(void)
41034191
Py_INCREF(&MethStatic_Type);
41044192
PyModule_AddObject(m,"MethStatic", (PyObject*)&MethStatic_Type);
41054193

4194+
if (PyType_Ready(&ObjExtraData_Type)<0)
4195+
returnNULL;
4196+
Py_INCREF(&ObjExtraData_Type);
4197+
PyModule_AddObject(m,"ObjExtraData", (PyObject*)&ObjExtraData_Type);
4198+
41064199
PyModule_AddObject(m,"CHAR_MAX",PyLong_FromLong(CHAR_MAX));
41074200
PyModule_AddObject(m,"CHAR_MIN",PyLong_FromLong(CHAR_MIN));
41084201
PyModule_AddObject(m,"UCHAR_MAX",PyLong_FromLong(UCHAR_MAX));

‎Modules/gcmodule.c‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2357,6 +2357,18 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
23572357
returnop;
23582358
}
23592359

2360+
PyObject*
2361+
PyUnstable_Object_GC_NewWithExtraData(PyTypeObject*tp,size_textra_size)
2362+
{
2363+
size_tpresize=_PyType_PreHeaderSize(tp);
2364+
PyObject*op=gc_alloc(_PyObject_SIZE(tp)+extra_size,presize);
2365+
if (op==NULL) {
2366+
returnNULL;
2367+
}
2368+
_PyObject_Init(op,tp);
2369+
returnop;
2370+
}
2371+
23602372
PyVarObject*
23612373
_PyObject_GC_Resize(PyVarObject*op,Py_ssize_tnitems)
23622374
{

‎Tools/c-analyzer/cpython/ignored.tsv‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@ Modules/_testcapimodule.c-g_dict_watch_events-
508508
Modules/_testcapimodule.c-g_dict_watchers_installed-
509509
Modules/_testcapimodule.c-g_type_modified_events-
510510
Modules/_testcapimodule.c-g_type_watchers_installed-
511+
Modules/_testcapimodule.c-ObjExtraData_Type-
511512
Modules/_testimportmultiple.c-_barmodule-
512513
Modules/_testimportmultiple.c-_foomodule-
513514
Modules/_testimportmultiple.c-_testimportmultiple-

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp