Skip to content

Commit d7aae08

Browse files
Erlend Egeberg Aaslandadorilson
Erlend Egeberg Aasland
authored andcommitted
bpo-40077: Convert mmap.mmap static type to a heap type (pythonGH-23108)
1 parent 33cd714 commit d7aae08

File tree

2 files changed

+91
-68
lines changed

2 files changed

+91
-68
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Convert :mod:`mmap` to use heap types.

Modules/mmapmodule.c

Lines changed: 90 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#define PY_SSIZE_T_CLEAN
2222
#include <Python.h>
23+
#include "structmember.h" // PyMemberDef
2324
#include <stddef.h> // offsetof()
2425

2526
#ifndef MS_WINDOWS
@@ -113,10 +114,23 @@ typedef struct {
113114
access_mode access;
114115
} mmap_object;
115116

117+
typedef struct {
118+
PyTypeObject *mmap_object_type;
119+
} mmap_state;
120+
121+
static mmap_state *
122+
get_mmap_state(PyObject *module)
123+
{
124+
mmap_state *state = PyModule_GetState(module);
125+
assert(state);
126+
return state;
127+
}
116128

117129
static void
118130
mmap_object_dealloc(mmap_object *m_obj)
119131
{
132+
PyTypeObject *tp = Py_TYPE(m_obj);
133+
120134
#ifdef MS_WINDOWS
121135
Py_BEGIN_ALLOW_THREADS
122136
if (m_obj->data != NULL)
@@ -142,7 +156,9 @@ mmap_object_dealloc(mmap_object *m_obj)
142156

143157
if (m_obj->weakreflist != NULL)
144158
PyObject_ClearWeakRefs((PyObject *) m_obj);
145-
Py_TYPE(m_obj)->tp_free((PyObject*)m_obj);
159+
160+
tp->tp_free(m_obj);
161+
Py_DECREF(tp);
146162
}
147163

148164
static PyObject *
@@ -793,6 +809,11 @@ mmap_madvise_method(mmap_object *self, PyObject *args)
793809
}
794810
#endif // HAVE_MADVISE
795811

812+
static struct PyMemberDef mmap_object_members[] = {
813+
{"__weaklistoffset__", T_PYSSIZET, offsetof(mmap_object, weakreflist), READONLY},
814+
{NULL},
815+
};
816+
796817
static struct PyMethodDef mmap_object_methods[] = {
797818
{"close", (PyCFunction) mmap_close_method, METH_NOARGS},
798819
{"find", (PyCFunction) mmap_find_method, METH_VARARGS},
@@ -1035,27 +1056,6 @@ mmap_ass_subscript(mmap_object *self, PyObject *item, PyObject *value)
10351056
}
10361057
}
10371058

1038-
static PySequenceMethods mmap_as_sequence = {
1039-
(lenfunc)mmap_length, /*sq_length*/
1040-
0, /*sq_concat*/
1041-
0, /*sq_repeat*/
1042-
(ssizeargfunc)mmap_item, /*sq_item*/
1043-
0, /*sq_slice*/
1044-
(ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/
1045-
0, /*sq_ass_slice*/
1046-
};
1047-
1048-
static PyMappingMethods mmap_as_mapping = {
1049-
(lenfunc)mmap_length,
1050-
(binaryfunc)mmap_subscript,
1051-
(objobjargproc)mmap_ass_subscript,
1052-
};
1053-
1054-
static PyBufferProcs mmap_as_buffer = {
1055-
(getbufferproc)mmap_buffer_getbuf,
1056-
(releasebufferproc)mmap_buffer_releasebuf,
1057-
};
1058-
10591059
static PyObject *
10601060
new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict);
10611061

@@ -1083,47 +1083,39 @@ The default value is MAP_SHARED.\n\
10831083
To map anonymous memory, pass -1 as the fileno (both versions).");
10841084

10851085

1086-
static PyTypeObject mmap_object_type = {
1087-
PyVarObject_HEAD_INIT(NULL, 0)
1088-
"mmap.mmap", /* tp_name */
1089-
sizeof(mmap_object), /* tp_basicsize */
1090-
0, /* tp_itemsize */
1091-
/* methods */
1092-
(destructor)mmap_object_dealloc, /* tp_dealloc */
1093-
0, /* tp_vectorcall_offset */
1094-
0, /* tp_getattr */
1095-
0, /* tp_setattr */
1096-
0, /* tp_as_async */
1097-
(reprfunc)mmap__repr__method, /* tp_repr */
1098-
0, /* tp_as_number */
1099-
&mmap_as_sequence, /* tp_as_sequence */
1100-
&mmap_as_mapping, /* tp_as_mapping */
1101-
0, /* tp_hash */
1102-
0, /* tp_call */
1103-
0, /* tp_str */
1104-
PyObject_GenericGetAttr, /* tp_getattro */
1105-
0, /* tp_setattro */
1106-
&mmap_as_buffer, /* tp_as_buffer */
1107-
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
1108-
mmap_doc, /* tp_doc */
1109-
0, /* tp_traverse */
1110-
0, /* tp_clear */
1111-
0, /* tp_richcompare */
1112-
offsetof(mmap_object, weakreflist), /* tp_weaklistoffset */
1113-
0, /* tp_iter */
1114-
0, /* tp_iternext */
1115-
mmap_object_methods, /* tp_methods */
1116-
0, /* tp_members */
1117-
mmap_object_getset, /* tp_getset */
1118-
0, /* tp_base */
1119-
0, /* tp_dict */
1120-
0, /* tp_descr_get */
1121-
0, /* tp_descr_set */
1122-
0, /* tp_dictoffset */
1123-
0, /* tp_init */
1124-
PyType_GenericAlloc, /* tp_alloc */
1125-
new_mmap_object, /* tp_new */
1126-
PyObject_Del, /* tp_free */
1086+
static PyType_Slot mmap_object_slots[] = {
1087+
{Py_tp_new, new_mmap_object},
1088+
{Py_tp_alloc, PyType_GenericAlloc},
1089+
{Py_tp_dealloc, mmap_object_dealloc},
1090+
{Py_tp_free, PyObject_Del},
1091+
{Py_tp_repr, mmap__repr__method},
1092+
{Py_tp_doc, (void *)mmap_doc},
1093+
{Py_tp_methods, mmap_object_methods},
1094+
{Py_tp_members, mmap_object_members},
1095+
{Py_tp_getset, mmap_object_getset},
1096+
{Py_tp_getattro, PyObject_GenericGetAttr},
1097+
1098+
/* as sequence */
1099+
{Py_sq_length, mmap_length},
1100+
{Py_sq_item, mmap_item},
1101+
{Py_sq_ass_item, mmap_ass_item},
1102+
1103+
/* as mapping */
1104+
{Py_mp_length, mmap_length},
1105+
{Py_mp_subscript, mmap_subscript},
1106+
{Py_mp_ass_subscript, mmap_ass_subscript},
1107+
1108+
/* as buffer */
1109+
{Py_bf_getbuffer, mmap_buffer_getbuf},
1110+
{Py_bf_releasebuffer, mmap_buffer_releasebuf},
1111+
{0, NULL},
1112+
};
1113+
1114+
static PyType_Spec mmap_object_spec = {
1115+
.name = "mmap.mmap",
1116+
.basicsize = sizeof(mmap_object),
1117+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1118+
.slots = mmap_object_slots,
11271119
};
11281120

11291121

@@ -1509,19 +1501,46 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
15091501
}
15101502
#endif /* MS_WINDOWS */
15111503

1504+
static int
1505+
mmap_traverse(PyObject *module, visitproc visit, void *arg)
1506+
{
1507+
mmap_state *state = get_mmap_state(module);
1508+
Py_VISIT(state->mmap_object_type);
1509+
return 0;
1510+
}
1511+
1512+
static int
1513+
mmap_clear(PyObject *module)
1514+
{
1515+
mmap_state *state = get_mmap_state(module);
1516+
Py_CLEAR(state->mmap_object_type);
1517+
return 0;
1518+
}
1519+
1520+
static void
1521+
mmap_free(void *module)
1522+
{
1523+
mmap_clear((PyObject *)module);
1524+
}
1525+
15121526
static int
15131527
mmap_exec(PyObject *module)
15141528
{
1515-
if (PyType_Ready(&mmap_object_type) < 0) {
1516-
return -1;
1517-
}
1529+
mmap_state *state = get_mmap_state(module);
15181530

15191531
Py_INCREF(PyExc_OSError);
15201532
if (PyModule_AddObject(module, "error", PyExc_OSError) < 0) {
15211533
Py_DECREF(PyExc_OSError);
15221534
return -1;
15231535
}
1524-
if (PyModule_AddType(module, &mmap_object_type) < 0) {
1536+
1537+
state->mmap_object_type = (PyTypeObject *)PyType_FromModuleAndSpec(module,
1538+
&mmap_object_spec,
1539+
NULL);
1540+
if (state->mmap_object_type == NULL) {
1541+
return -1;
1542+
}
1543+
if (PyModule_AddType(module, state->mmap_object_type) < 0) {
15251544
return -1;
15261545
}
15271546

@@ -1660,8 +1679,11 @@ static PyModuleDef_Slot mmap_slots[] = {
16601679
static struct PyModuleDef mmapmodule = {
16611680
PyModuleDef_HEAD_INIT,
16621681
.m_name = "mmap",
1663-
.m_size = 0,
1682+
.m_size = sizeof(mmap_state),
16641683
.m_slots = mmap_slots,
1684+
.m_traverse = mmap_traverse,
1685+
.m_clear = mmap_clear,
1686+
.m_free = mmap_free,
16651687
};
16661688

16671689
PyMODINIT_FUNC

0 commit comments

Comments
 (0)