diff -r f7ea11f8da52 Modules/mmapmodule.c --- a/Modules/mmapmodule.c Thu Aug 16 10:54:44 2012 +0200 +++ b/Modules/mmapmodule.c Thu Aug 16 11:02:28 2012 +0200 @@ -73,6 +73,37 @@ #include #endif /* HAVE_SYS_TYPES_H */ +typedef struct { + PyObject *mmap_object_type; +} mmapstate; + + +#define mmap_state(o) ((mmapstate *)PyModule_GetState(o)) + +static int +mmap_clear(PyObject *m) +{ + Py_CLEAR(mmap_state(m)->mmap_object_type); + return 0; +} + +static int +mmap_traverse(PyObject *m, visitproc visit, void *arg) +{ + Py_VISIT(mmap_state(m)->mmap_object_type); + return 0; +} + +static void +mmap_free(void *m) +{ + mmap_clear((PyObject *)m); +} + +static PyModuleDef mmapmodule; + +#define mmapstate_global ((mmapstate *)PyModule_GetState(PyState_FindModule(&mmapmodule))) + /* Prefer MAP_ANONYMOUS since MAP_ANON is deprecated according to man page. */ #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) # define MAP_ANONYMOUS MAP_ANON @@ -115,6 +146,7 @@ static void mmap_object_dealloc(mmap_object *m_obj) { + PyTypeObject *type = Py_TYPE(m_obj); #ifdef MS_WINDOWS if (m_obj->data != NULL) UnmapViewOfFile (m_obj->data); @@ -134,7 +166,10 @@ } #endif /* UNIX */ - Py_TYPE(m_obj)->tp_free((PyObject*)m_obj); + type->tp_free((PyObject*)m_obj); + if((void *)type->tp_dealloc == (void *)mmap_object_dealloc) { + Py_DECREF(type); + } } static PyObject * @@ -958,22 +993,6 @@ } } -static PySequenceMethods mmap_as_sequence = { - (lenfunc)mmap_length, /*sq_length*/ - (binaryfunc)mmap_concat, /*sq_concat*/ - (ssizeargfunc)mmap_repeat, /*sq_repeat*/ - (ssizeargfunc)mmap_item, /*sq_item*/ - 0, /*sq_slice*/ - (ssizeobjargproc)mmap_ass_item, /*sq_ass_item*/ - 0, /*sq_ass_slice*/ -}; - -static PyMappingMethods mmap_as_mapping = { - (lenfunc)mmap_length, - (binaryfunc)mmap_subscript, - (objobjargproc)mmap_ass_subscript, -}; - static PyBufferProcs mmap_as_buffer = { (getbufferproc)mmap_buffer_getbuf, (releasebufferproc)mmap_buffer_releasebuf, @@ -984,7 +1003,6 @@ PyDoc_STRVAR(mmap_doc, "Windows: mmap(fileno, length[, tagname[, access[, offset]]])\n\ -\n\ Maps length bytes from the file specified by the file handle fileno,\n\ and returns a mmap object. If length is larger than the current size\n\ of the file, the file is extended to contain length bytes. If length\n\ @@ -1006,49 +1024,35 @@ To map anonymous memory, pass -1 as the fileno (both versions)."); -static PyTypeObject mmap_object_type = { - PyVarObject_HEAD_INIT(NULL, 0) - "mmap.mmap", /* tp_name */ - sizeof(mmap_object), /* tp_size */ - 0, /* tp_itemsize */ - /* methods */ - (destructor) mmap_object_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - &mmap_as_sequence, /*tp_as_sequence*/ - &mmap_as_mapping, /*tp_as_mapping*/ - 0, /*tp_hash*/ - 0, /*tp_call*/ - 0, /*tp_str*/ - PyObject_GenericGetAttr, /*tp_getattro*/ - 0, /*tp_setattro*/ - &mmap_as_buffer, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ - mmap_doc, /*tp_doc*/ - 0, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - mmap_object_methods, /* tp_methods */ - 0, /* tp_members */ - mmap_object_getset, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - 0, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - new_mmap_object, /* tp_new */ - PyObject_Del, /* tp_free */ +static PyType_Slot mmap_object_type_slots[] = { + {Py_tp_dealloc, (destructor) mmap_object_dealloc}, + {Py_sq_length, (lenfunc)mmap_length}, + {Py_sq_concat, (binaryfunc)mmap_concat}, + {Py_sq_repeat, (ssizeargfunc)mmap_repeat}, + {Py_sq_item, (ssizeargfunc)mmap_item}, + {Py_sq_ass_item, (ssizeobjargproc)mmap_ass_item}, + {Py_mp_length, (lenfunc)mmap_length}, + {Py_mp_subscript, (binaryfunc)mmap_subscript}, + {Py_mp_ass_subscript, (objobjargproc)mmap_ass_subscript}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, mmap_doc}, + {Py_tp_methods, mmap_object_methods}, + {Py_tp_getset, mmap_object_getset}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, new_mmap_object}, + {Py_tp_free, PyObject_Del}, + {0, 0} }; +static PyType_Spec mmap_object_type_spec = { + "mmap.mmap", + sizeof(mmap_object), + 0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + mmap_object_type_slots, +}; + + /* extract the map size from the given PyObject @@ -1445,12 +1449,12 @@ PyModuleDef_HEAD_INIT, "mmap", NULL, - -1, + sizeof(mmapstate), NULL, NULL, - NULL, - NULL, - NULL + mmap_traverse, + mmap_clear, + mmap_free }; PyMODINIT_FUNC @@ -1458,17 +1462,23 @@ { PyObject *dict, *module; - if (PyType_Ready(&mmap_object_type) < 0) - return NULL; - module = PyModule_Create(&mmapmodule); if (module == NULL) return NULL; dict = PyModule_GetDict(module); if (!dict) return NULL; + + mmap_state(module)->mmap_object_type = PyType_FromSpec(&mmap_object_type_spec); + if (mmap_state(module)->mmap_object_type == NULL) + return NULL; + + ((PyTypeObject *)mmap_state(module)->mmap_object_type)->tp_as_buffer = + &mmap_as_buffer; + PyDict_SetItemString(dict, "error", PyExc_OSError); - PyDict_SetItemString(dict, "mmap", (PyObject*) &mmap_object_type); + Py_INCREF(mmap_state(module)->mmap_object_type); + PyDict_SetItemString(dict, "mmap", mmap_state(module)->mmap_object_type); #ifdef PROT_EXEC setint(dict, "PROT_EXEC", PROT_EXEC); #endif