gh-76785: Simplify Channels XID Types (gh-116318)

I had added an extra cleanup abstraction a while back that has turned out to be unnecessary.
This commit is contained in:
Eric Snow 2024-03-04 12:32:39 -07:00 committed by GitHub
parent ffed8d985b
commit 01440d3a39
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 50 additions and 79 deletions

View File

@ -93,38 +93,6 @@ API.. The module does not create any objects that are shared globally.
PyMem_RawFree(VAR)
struct xid_class_registry {
size_t count;
#define MAX_XID_CLASSES 5
struct {
PyTypeObject *cls;
} added[MAX_XID_CLASSES];
};
static int
register_xid_class(PyTypeObject *cls, crossinterpdatafunc shared,
struct xid_class_registry *classes)
{
int res = ensure_xid_class(cls, shared);
if (res == 0) {
assert(classes->count < MAX_XID_CLASSES);
// The class has refs elsewhere, so we need to incref here.
classes->added[classes->count].cls = cls;
classes->count += 1;
}
return res;
}
static void
clear_xid_class_registry(struct xid_class_registry *classes)
{
while (classes->count > 0) {
classes->count -= 1;
PyTypeObject *cls = classes->added[classes->count].cls;
_PyCrossInterpreterData_UnregisterClass(cls);
}
}
#define XID_IGNORE_EXC 1
#define XID_FREE 2
@ -223,28 +191,6 @@ add_new_exception(PyObject *mod, const char *name, PyObject *base)
#define ADD_NEW_EXCEPTION(MOD, NAME, BASE) \
add_new_exception(MOD, MODULE_NAME_STR "." Py_STRINGIFY(NAME), BASE)
static PyTypeObject *
add_new_type(PyObject *mod, PyType_Spec *spec, crossinterpdatafunc shared,
struct xid_class_registry *classes)
{
PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec(
mod, spec, NULL);
if (cls == NULL) {
return NULL;
}
if (PyModule_AddType(mod, cls) < 0) {
Py_DECREF(cls);
return NULL;
}
if (shared != NULL) {
if (register_xid_class(cls, shared, classes)) {
Py_DECREF(cls);
return NULL;
}
}
return cls;
}
static int
wait_for_lock(PyThread_type_lock mutex, PY_TIMEOUT_T timeout)
{
@ -269,8 +215,6 @@ wait_for_lock(PyThread_type_lock mutex, PY_TIMEOUT_T timeout)
/* module state *************************************************************/
typedef struct {
struct xid_class_registry xid_classes;
/* Added at runtime by interpreters module. */
PyTypeObject *send_channel_type;
PyTypeObject *recv_channel_type;
@ -332,19 +276,33 @@ traverse_module_state(module_state *state, visitproc visit, void *arg)
return 0;
}
static void
clear_xid_types(module_state *state)
{
/* external types */
if (state->send_channel_type != NULL) {
(void)_PyCrossInterpreterData_UnregisterClass(state->send_channel_type);
Py_CLEAR(state->send_channel_type);
}
if (state->recv_channel_type != NULL) {
(void)_PyCrossInterpreterData_UnregisterClass(state->recv_channel_type);
Py_CLEAR(state->recv_channel_type);
}
/* heap types */
if (state->ChannelIDType != NULL) {
(void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType);
Py_CLEAR(state->ChannelIDType);
}
}
static int
clear_module_state(module_state *state)
{
/* external types */
Py_CLEAR(state->send_channel_type);
Py_CLEAR(state->recv_channel_type);
clear_xid_types(state);
/* heap types */
Py_CLEAR(state->ChannelInfoType);
if (state->ChannelIDType != NULL) {
(void)_PyCrossInterpreterData_UnregisterClass(state->ChannelIDType);
}
Py_CLEAR(state->ChannelIDType);
/* exceptions */
Py_CLEAR(state->ChannelError);
@ -2614,6 +2572,25 @@ static PyType_Spec channelid_typespec = {
.slots = channelid_typeslots,
};
static PyTypeObject *
add_channelid_type(PyObject *mod)
{
PyTypeObject *cls = (PyTypeObject *)PyType_FromModuleAndSpec(
mod, &channelid_typespec, NULL);
if (cls == NULL) {
return NULL;
}
if (PyModule_AddType(mod, cls) < 0) {
Py_DECREF(cls);
return NULL;
}
if (ensure_xid_class(cls, _channelid_shared) < 0) {
Py_DECREF(cls);
return NULL;
}
return cls;
}
/* SendChannel and RecvChannel classes */
@ -2697,7 +2674,6 @@ set_channelend_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
if (state == NULL) {
return -1;
}
struct xid_class_registry *xid_classes = &state->xid_classes;
if (state->send_channel_type != NULL
|| state->recv_channel_type != NULL)
@ -2707,11 +2683,15 @@ set_channelend_types(PyObject *mod, PyTypeObject *send, PyTypeObject *recv)
}
state->send_channel_type = (PyTypeObject *)Py_NewRef(send);
state->recv_channel_type = (PyTypeObject *)Py_NewRef(recv);
if (register_xid_class(send, _channelend_shared, xid_classes)) {
if (ensure_xid_class(send, _channelend_shared) < 0) {
Py_CLEAR(state->send_channel_type);
Py_CLEAR(state->recv_channel_type);
return -1;
}
if (register_xid_class(recv, _channelend_shared, xid_classes)) {
if (ensure_xid_class(recv, _channelend_shared) < 0) {
(void)_PyCrossInterpreterData_UnregisterClass(state->send_channel_type);
Py_CLEAR(state->send_channel_type);
Py_CLEAR(state->recv_channel_type);
return -1;
}
@ -3294,13 +3274,11 @@ module_exec(PyObject *mod)
if (_globals_init() != 0) {
return -1;
}
struct xid_class_registry *xid_classes = NULL;
module_state *state = get_module_state(mod);
if (state == NULL) {
goto error;
}
xid_classes = &state->xid_classes;
/* Add exception types */
if (exceptions_init(mod) != 0) {
@ -3319,8 +3297,7 @@ module_exec(PyObject *mod)
}
// ChannelID
state->ChannelIDType = add_new_type(
mod, &channelid_typespec, _channelid_shared, xid_classes);
state->ChannelIDType = add_channelid_type(mod);
if (state->ChannelIDType == NULL) {
goto error;
}
@ -3332,8 +3309,8 @@ module_exec(PyObject *mod)
return 0;
error:
if (xid_classes != NULL) {
clear_xid_class_registry(xid_classes);
if (state != NULL) {
clear_xid_types(state);
}
_globals_fini();
return -1;
@ -3360,9 +3337,6 @@ module_clear(PyObject *mod)
module_state *state = get_module_state(mod);
assert(state != NULL);
// Before clearing anything, we unregister the various XID types. */
clear_xid_class_registry(&state->xid_classes);
// Now we clear the module state.
clear_module_state(state);
return 0;
@ -3374,9 +3348,6 @@ module_free(void *mod)
module_state *state = get_module_state(mod);
assert(state != NULL);
// Before clearing anything, we unregister the various XID types. */
clear_xid_class_registry(&state->xid_classes);
// Now we clear the module state.
clear_module_state(state);