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
117129static void
118130mmap_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
148164static 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+
796817static 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-
10591059static PyObject *
10601060new_mmap_object (PyTypeObject * type , PyObject * args , PyObject * kwdict );
10611061
@@ -1083,47 +1083,39 @@ The default value is MAP_SHARED.\n\
10831083To 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+
15121526static int
15131527mmap_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[] = {
16601679static 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
16671689PyMODINIT_FUNC
0 commit comments