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

Commit87223f3

Browse files
jbradaricencukouerlend-aasland
authored
gh-103743: Add PyUnstable_Object_GC_NewWithExtraData (GH-103744)
Co-authored-by: Petr Viktorin <encukou@gmail.com>Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>
1 parentf6314b9 commit87223f3

File tree

6 files changed

+156
-2
lines changed

6 files changed

+156
-2
lines changed

‎Doc/c-api/gcsupport.rst‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,31 @@ rules:
5959
Analogous to:c:func:`PyObject_New` but for container objects with the
6060
:const:`Py_TPFLAGS_HAVE_GC` flag set.
6161
62-
6362
..c:function:: TYPE*PyObject_GC_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)
6463
6564
Analogous to:c:func:`PyObject_NewVar` but for container objects with the
6665
:const:`Py_TPFLAGS_HAVE_GC` flag set.
6766
67+
..c:function:: PyObject*PyUnstable_Object_GC_NewWithExtraData(PyTypeObject *type, size_t extra_size)
68+
69+
Analogous to:c:func:`PyObject_GC_New` but allocates *extra_size*
70+
bytes at the end of the object (at offset
71+
:c:member:`~PyTypeObject.tp_basicsize`).
72+
The allocated memory is initialized to zeros,
73+
except for the :c:type:`Python object header <PyObject>`.
74+
75+
The extra data will be deallocated with the object, but otherwise it is
76+
not managed by Python.
77+
78+
.. warning::
79+
The function is marked as unstable because thefinal mechanism
80+
for reserving extra data after an instance is not yet decided.
81+
For allocating a variable number of fields, prefer using
82+
:c:type:`PyVarObject` and :c:member:`~PyTypeObject.tp_itemsize`
83+
instead.
84+
85+
.. versionadded:: 3.12
86+
6887
6988
.. c:function:: TYPE* PyObject_GC_Resize(TYPE, PyVarObject *op, Py_ssize_t newsize)
7089

‎Include/cpython/objimpl.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,6 @@ PyAPI_FUNC(int) PyObject_IS_GC(PyObject *obj);
9090
PyAPI_FUNC(int)PyType_SUPPORTS_WEAKREFS(PyTypeObject*type);
9191

9292
PyAPI_FUNC(PyObject**)PyObject_GET_WEAKREFS_LISTPTR(PyObject*op);
93+
94+
PyAPI_FUNC(PyObject*)PyUnstable_Object_GC_NewWithExtraData(PyTypeObject*,
95+
size_t);

‎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:c:func:`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: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3363,7 +3363,7 @@ test_gc_visit_objects_basic(PyObject *Py_UNUSED(self),
33633363
}
33643364
state.target=obj;
33653365
state.found=0;
3366-
3366+
33673367
PyUnstable_GC_VisitObjects(gc_visit_callback_basic,&state);
33683368
Py_DECREF(obj);
33693369
if (!state.found) {
@@ -3400,6 +3400,98 @@ test_gc_visit_objects_exit_early(PyObject *Py_UNUSED(self),
34003400
Py_RETURN_NONE;
34013401
}
34023402

3403+
typedefstruct {
3404+
PyObject_HEAD
3405+
}ObjExtraData;
3406+
3407+
staticPyObject*
3408+
obj_extra_data_new(PyTypeObject*type,PyObject*args,PyObject*kwds)
3409+
{
3410+
size_textra_size=sizeof(PyObject*);
3411+
PyObject*obj=PyUnstable_Object_GC_NewWithExtraData(type,extra_size);
3412+
if (obj==NULL) {
3413+
returnPyErr_NoMemory();
3414+
}
3415+
PyObject_GC_Track(obj);
3416+
returnobj;
3417+
}
3418+
3419+
staticPyObject**
3420+
obj_extra_data_get_extra_storage(PyObject*self)
3421+
{
3422+
return (PyObject**)((char*)self+Py_TYPE(self)->tp_basicsize);
3423+
}
3424+
3425+
staticPyObject*
3426+
obj_extra_data_get(PyObject*self,void*Py_UNUSED(ignored))
3427+
{
3428+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3429+
PyObject*value=*extra_storage;
3430+
if (!value) {
3431+
Py_RETURN_NONE;
3432+
}
3433+
returnPy_NewRef(value);
3434+
}
3435+
3436+
staticint
3437+
obj_extra_data_set(PyObject*self,PyObject*newval,void*Py_UNUSED(ignored))
3438+
{
3439+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3440+
Py_CLEAR(*extra_storage);
3441+
if (newval) {
3442+
*extra_storage=Py_NewRef(newval);
3443+
}
3444+
return0;
3445+
}
3446+
3447+
staticPyGetSetDefobj_extra_data_getset[]= {
3448+
{"extra", (getter)obj_extra_data_get, (setter)obj_extra_data_set,NULL},
3449+
{NULL}
3450+
};
3451+
3452+
staticint
3453+
obj_extra_data_traverse(PyObject*self,visitprocvisit,void*arg)
3454+
{
3455+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3456+
PyObject*value=*extra_storage;
3457+
Py_VISIT(value);
3458+
return0;
3459+
}
3460+
3461+
staticint
3462+
obj_extra_data_clear(PyObject*self)
3463+
{
3464+
PyObject**extra_storage=obj_extra_data_get_extra_storage(self);
3465+
Py_CLEAR(*extra_storage);
3466+
return0;
3467+
}
3468+
3469+
staticvoid
3470+
obj_extra_data_dealloc(PyObject*self)
3471+
{
3472+
PyTypeObject*tp=Py_TYPE(self);
3473+
PyObject_GC_UnTrack(self);
3474+
obj_extra_data_clear(self);
3475+
tp->tp_free(self);
3476+
Py_DECREF(tp);
3477+
}
3478+
3479+
staticPyType_SlotObjExtraData_Slots[]= {
3480+
{Py_tp_getset,obj_extra_data_getset},
3481+
{Py_tp_dealloc,obj_extra_data_dealloc},
3482+
{Py_tp_traverse,obj_extra_data_traverse},
3483+
{Py_tp_clear,obj_extra_data_clear},
3484+
{Py_tp_new,obj_extra_data_new},
3485+
{Py_tp_free,PyObject_GC_Del},
3486+
{0,NULL},
3487+
};
3488+
3489+
staticPyType_SpecObjExtraData_TypeSpec= {
3490+
.name="_testcapi.ObjExtraData",
3491+
.basicsize=sizeof(ObjExtraData),
3492+
.flags=Py_TPFLAGS_DEFAULT |Py_TPFLAGS_BASETYPE |Py_TPFLAGS_HAVE_GC,
3493+
.slots=ObjExtraData_Slots,
3494+
};
34033495

34043496
structatexit_data {
34053497
intcalled;
@@ -4124,6 +4216,17 @@ PyInit__testcapi(void)
41244216
Py_INCREF(&MethStatic_Type);
41254217
PyModule_AddObject(m,"MethStatic", (PyObject*)&MethStatic_Type);
41264218

4219+
PyObject*ObjExtraData_Type=PyType_FromModuleAndSpec(
4220+
m,&ObjExtraData_TypeSpec,NULL);
4221+
if (ObjExtraData_Type==0) {
4222+
returnNULL;
4223+
}
4224+
intret=PyModule_AddType(m, (PyTypeObject*)ObjExtraData_Type);
4225+
Py_DECREF(&ObjExtraData_Type);
4226+
if (ret<0) {
4227+
returnNULL;
4228+
}
4229+
41274230
PyModule_AddObject(m,"CHAR_MAX",PyLong_FromLong(CHAR_MAX));
41284231
PyModule_AddObject(m,"CHAR_MIN",PyLong_FromLong(CHAR_MIN));
41294232
PyModule_AddObject(m,"UCHAR_MAX",PyLong_FromLong(UCHAR_MAX));

‎Modules/gcmodule.c‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2367,6 +2367,19 @@ _PyObject_GC_NewVar(PyTypeObject *tp, Py_ssize_t nitems)
23672367
returnop;
23682368
}
23692369

2370+
PyObject*
2371+
PyUnstable_Object_GC_NewWithExtraData(PyTypeObject*tp,size_textra_size)
2372+
{
2373+
size_tpresize=_PyType_PreHeaderSize(tp);
2374+
PyObject*op=gc_alloc(_PyObject_SIZE(tp)+extra_size,presize);
2375+
if (op==NULL) {
2376+
returnNULL;
2377+
}
2378+
memset(op,0,_PyObject_SIZE(tp)+extra_size);
2379+
_PyObject_Init(op,tp);
2380+
returnop;
2381+
}
2382+
23702383
PyVarObject*
23712384
_PyObject_GC_Resize(PyVarObject*op,Py_ssize_tnitems)
23722385
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp