|
Expand Up
|
@@ -20,13 +20,26 @@ _Py_IDENTIFIER(_abc_impl); |
|
|
_Py_IDENTIFIER(__subclasscheck__); |
|
|
_Py_IDENTIFIER(__subclasshook__); |
|
|
|
|
|
typedef struct { |
|
|
PyTypeObject *_abc_data_type; |
|
|
} _abcmodule_state; |
|
|
|
|
|
/* A global counter that is incremented each time a class is |
|
|
registered as a virtual subclass of anything. It forces the |
|
|
negative cache to be cleared before its next use. |
|
|
Note: this counter is private. Use `abc.get_cache_token()` for |
|
|
external code. */ |
|
|
// FIXME: PEP 573: Move abc_invalidation_counter into _abcmodule_state. |
|
|
static unsigned long long abc_invalidation_counter = 0; |
Comment thread
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that the abc_invalidation_counter is okay to be shared as static from interpreter Isolation point of view.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move this into PyInterpreterState?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like it would be safe to put it in the module state. The purpose of the counter is to invalidate the module cache. Registering a class in module instance 1 should not invalidate module instance 2. What do you think?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I 've updated the PR.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
|
|
|
|
|
static inline _abcmodule_state* |
|
|
get_abc_state(PyObject *module) |
|
|
{ |
|
|
void *state = PyModule_GetState(module); |
|
|
assert(state != NULL); |
|
|
return (_abcmodule_state *)state; |
|
|
} |
|
|
|
|
|
/* This object stores internal state for ABCs. |
|
|
Note that we can use normal sets for caches, |
|
|
since they are never iterated over. */ |
|
Expand All
|
@@ -41,10 +54,12 @@ typedef struct { |
|
|
static void |
|
|
abc_data_dealloc(_abc_data *self) |
|
|
{ |
|
|
PyTypeObject *tp = Py_TYPE(self); |
|
|
Py_XDECREF(self->_abc_registry); |
|
|
Py_XDECREF(self->_abc_cache); |
|
|
Py_XDECREF(self->_abc_negative_cache); |
|
|
Py_TYPE(self)->tp_free(self); |
|
|
tp->tp_free(self); |
|
|
Py_DECREF(tp); |
|
|
} |
|
|
|
|
|
static PyObject * |
|
Expand All
|
@@ -65,24 +80,29 @@ abc_data_new(PyTypeObject *type, PyObject *args, PyObject *kwds) |
|
|
PyDoc_STRVAR(abc_data_doc, |
|
|
"Internal state held by ABC machinery."); |
|
|
|
|
|
static PyTypeObject _abc_data_type = { |
|
|
PyVarObject_HEAD_INIT(NULL, 0) |
|
|
"_abc_data", /*tp_name*/ |
|
|
sizeof(_abc_data), /*tp_basicsize*/ |
|
|
.tp_dealloc = (destructor)abc_data_dealloc, |
|
|
.tp_flags = Py_TPFLAGS_DEFAULT, |
|
|
.tp_alloc = PyType_GenericAlloc, |
|
|
.tp_new = abc_data_new, |
|
|
static PyType_Slot _abc_data_type_spec_slots[] = { |
|
|
{Py_tp_doc, (void *)abc_data_doc}, |
|
|
{Py_tp_new, abc_data_new}, |
|
|
{Py_tp_dealloc, abc_data_dealloc}, |
|
|
{0, 0} |
|
|
}; |
|
|
|
|
|
static PyType_Spec _abc_data_type_spec = { |
|
|
.name = "_abc._abc_data", |
|
|
.basicsize = sizeof(_abc_data), |
|
|
.flags = Py_TPFLAGS_DEFAULT, |
|
|
.slots = _abc_data_type_spec_slots, |
|
|
}; |
|
|
|
|
|
static _abc_data * |
|
|
_get_impl(PyObject *self) |
|
|
_get_impl(PyObject *module, PyObject *self) |
|
|
{ |
|
|
_abcmodule_state *state = get_abc_state(module); |
|
|
PyObject *impl = _PyObject_GetAttrId(self, &PyId__abc_impl); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
|
if (!Py_IS_TYPE(impl, &_abc_data_type)) { |
|
|
if (!Py_IS_TYPE(impl, state->_abc_data_type)) { |
|
|
PyErr_SetString(PyExc_TypeError, "_abc_impl is set to a wrong type"); |
|
|
Py_DECREF(impl); |
|
|
return NULL; |
|
Expand Down
Expand Up
|
@@ -179,7 +199,7 @@ static PyObject * |
|
|
_abc__reset_registry(PyObject *module, PyObject *self) |
|
|
/*[clinic end generated code: output=92d591a43566cc10 input=12a0b7eb339ac35c]*/ |
|
|
{ |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand All
|
@@ -206,7 +226,7 @@ static PyObject * |
|
|
_abc__reset_caches(PyObject *module, PyObject *self) |
|
|
/*[clinic end generated code: output=f296f0d5c513f80c input=c0ac616fd8acfb6f]*/ |
|
|
{ |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -241,7 +261,7 @@ static PyObject * |
|
|
_abc__get_dump(PyObject *module, PyObject *self) |
|
|
/*[clinic end generated code: output=9d9569a8e2c1c443 input=2c5deb1bfe9e3c79]*/ |
|
|
{ |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -391,13 +411,14 @@ static PyObject * |
|
|
_abc__abc_init(PyObject *module, PyObject *self) |
|
|
/*[clinic end generated code: output=594757375714cda1 input=8d7fe470ff77f029]*/ |
|
|
{ |
|
|
_abcmodule_state *state = get_abc_state(module); |
|
|
PyObject *data; |
|
|
if (compute_abstract_methods(self) < 0) { |
|
|
return NULL; |
|
|
} |
|
|
|
|
|
/* Set up inheritance registry. */ |
|
|
data = abc_data_new(&_abc_data_type, NULL, NULL); |
|
|
data = abc_data_new(state->_abc_data_type, NULL, NULL); |
|
|
if (data == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -446,7 +467,7 @@ _abc__abc_register_impl(PyObject *module, PyObject *self, PyObject *subclass) |
|
|
if (result < 0) { |
|
|
return NULL; |
|
|
} |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -480,7 +501,7 @@ _abc__abc_instancecheck_impl(PyObject *module, PyObject *self, |
|
|
/*[clinic end generated code: output=b8b5148f63b6b56f input=a4f4525679261084]*/ |
|
|
{ |
|
|
PyObject *subtype, *result = NULL, *subclass = NULL; |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -576,7 +597,7 @@ _abc__abc_subclasscheck_impl(PyObject *module, PyObject *self, |
|
|
PyObject *ok, *subclasses = NULL, *result = NULL; |
|
|
Py_ssize_t pos; |
|
|
int incache; |
|
|
_abc_data *impl = _get_impl(self); |
|
|
_abc_data *impl = _get_impl(module, self); |
|
|
if (impl == NULL) { |
|
|
return NULL; |
|
|
} |
|
Expand Down
Expand Up
|
@@ -795,7 +816,7 @@ _abc_get_cache_token_impl(PyObject *module) |
|
|
return PyLong_FromUnsignedLongLong(abc_invalidation_counter); |
|
|
} |
|
|
|
|
|
static struct PyMethodDef module_functions[] = { |
|
|
static struct PyMethodDef _abcmodule_methods[] = { |
|
|
_ABC_GET_CACHE_TOKEN_METHODDEF |
|
|
_ABC__ABC_INIT_METHODDEF |
|
|
_ABC__RESET_REGISTRY_METHODDEF |
|
Expand All
|
@@ -808,30 +829,54 @@ static struct PyMethodDef module_functions[] = { |
|
|
}; |
|
|
|
|
|
static int |
|
|
_abc_exec(PyObject *module) |
|
|
_abcmodule_exec(PyObject *module) |
|
|
{ |
|
|
if (PyType_Ready(&_abc_data_type) < 0) { |
|
|
_abcmodule_state *state = get_abc_state(module); |
|
|
state->_abc_data_type = (PyTypeObject *)PyType_FromSpec(&_abc_data_type_spec); |
|
|
if (state->_abc_data_type == NULL) { |
|
|
return -1; |
|
|
} |
|
|
_abc_data_type.tp_doc = abc_data_doc; |
|
|
|
|
|
return 0; |
|
|
} |
|
|
|
|
|
static int |
|
|
_abcmodule_traverse(PyObject *module, visitproc visit, void *arg) |
|
|
{ |
|
|
_abcmodule_state *state = get_abc_state(module); |
|
|
Py_VISIT(state->_abc_data_type); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
static PyModuleDef_Slot _abc_slots[] = { |
|
|
{Py_mod_exec, _abc_exec}, |
|
|
static int |
|
|
_abcmodule_clear(PyObject *module) |
|
|
{ |
|
|
_abcmodule_state *state = get_abc_state(module); |
|
|
Py_CLEAR(state->_abc_data_type); |
|
|
return 0; |
|
|
} |
|
|
|
|
|
static void |
|
|
_abcmodule_free(void *module) |
|
|
{ |
|
|
_abcmodule_clear((PyObject *)module); |
|
|
} |
|
|
|
|
|
static PyModuleDef_Slot _abcmodule_slots[] = { |
|
|
{Py_mod_exec, _abcmodule_exec}, |
|
|
{0, NULL} |
|
|
}; |
|
|
|
|
|
static struct PyModuleDef _abcmodule = { |
|
|
PyModuleDef_HEAD_INIT, |
|
|
"_abc", |
|
|
_abc__doc__, |
|
|
0, |
|
|
module_functions, |
|
|
_abc_slots, |
|
|
NULL, |
|
|
NULL, |
|
|
NULL |
|
|
sizeof(_abcmodule_state), |
|
|
_abcmodule_methods, |
|
|
_abcmodule_slots, |
|
|
_abcmodule_traverse, |
|
|
_abcmodule_clear, |
|
|
_abcmodule_free, |
|
|
}; |
|
|
|
|
|
PyMODINIT_FUNC |
|
Expand Down
|
|