diff options
-rw-r--r-- | Modules/_sqlite/cache.c | 83 | ||||
-rw-r--r-- | Modules/_sqlite/connection.c | 58 | ||||
-rw-r--r-- | Modules/_sqlite/cursor.c | 46 | ||||
-rw-r--r-- | Modules/_sqlite/prepare_protocol.c | 13 | ||||
-rw-r--r-- | Modules/_sqlite/row.c | 29 | ||||
-rw-r--r-- | Modules/_sqlite/statement.c | 33 |
6 files changed, 190 insertions, 72 deletions
diff --git a/Modules/_sqlite/cache.c b/Modules/_sqlite/cache.c index 8da0a64..e0a1707 100644 --- a/Modules/_sqlite/cache.c +++ b/Modules/_sqlite/cache.c @@ -44,14 +44,29 @@ pysqlite_new_node(PyObject *key, PyObject *data) return node; } +static int +node_traverse(pysqlite_Node *self, visitproc visit, void *arg) +{ + Py_VISIT(self->key); + Py_VISIT(self->data); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +node_clear(pysqlite_Node *self) +{ + Py_CLEAR(self->key); + Py_CLEAR(self->data); + return 0; +} + static void pysqlite_node_dealloc(pysqlite_Node *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_DECREF(self->key); - Py_DECREF(self->data); - + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -88,31 +103,51 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs) return 0; } -static void -pysqlite_cache_dealloc(pysqlite_Cache *self) +static int +cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); - pysqlite_Node* node; - pysqlite_Node* delete_node; - - if (!self->factory) { - /* constructor failed, just get out of here */ - return; + pysqlite_Node *node = self->first; + while (node) { + Py_VISIT(node); + node = node->next; + } + Py_VISIT(self->mapping); + if (self->decref_factory) { + Py_VISIT(self->factory); } + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cache_clear(pysqlite_Cache *self) +{ /* iterate over all nodes and deallocate them */ - node = self->first; + pysqlite_Node *node = self->first; + self->first = NULL; while (node) { - delete_node = node; + pysqlite_Node *delete_node = node; node = node->next; - Py_DECREF(delete_node); + Py_CLEAR(delete_node); } - if (self->decref_factory) { - Py_DECREF(self->factory); + Py_CLEAR(self->factory); + } + Py_CLEAR(self->mapping); + return 0; +} + +static void +pysqlite_cache_dealloc(pysqlite_Cache *self) +{ + if (!self->factory) { + /* constructor failed, just get out of here */ + return; } - Py_DECREF(self->mapping); + PyObject_GC_UnTrack(self); + PyTypeObject *tp = Py_TYPE(self); + tp->tp_clear((PyObject *)self); tp->tp_free(self); Py_DECREF(tp); } @@ -260,14 +295,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args) static PyType_Slot node_slots[] = { {Py_tp_dealloc, pysqlite_node_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_traverse, node_traverse}, + {Py_tp_clear, node_clear}, {0, NULL}, }; static PyType_Spec node_spec = { .name = MODULE_NAME ".Node", .basicsize = sizeof(pysqlite_Node), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = node_slots, }; PyTypeObject *pysqlite_NodeType = NULL; @@ -283,15 +319,16 @@ static PyMethodDef cache_methods[] = { static PyType_Slot cache_slots[] = { {Py_tp_dealloc, pysqlite_cache_dealloc}, {Py_tp_methods, cache_methods}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cache_init}, + {Py_tp_traverse, cache_traverse}, + {Py_tp_clear, cache_clear}, {0, NULL}, }; static PyType_Spec cache_spec = { .name = MODULE_NAME ".Cache", .basicsize = sizeof(pysqlite_Cache), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cache_slots, }; PyTypeObject *pysqlite_CacheType = NULL; diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c index 2893272..47d97d1 100644 --- a/Modules/_sqlite/connection.c +++ b/Modules/_sqlite/connection.c @@ -225,28 +225,51 @@ pysqlite_do_all_statements(pysqlite_Connection *self, int action, } } +static int +connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg) +{ + Py_VISIT(self->statement_cache); + Py_VISIT(self->isolation_level); + Py_VISIT(self->function_pinboard_trace_callback); + Py_VISIT(self->function_pinboard_progress_handler); + Py_VISIT(self->function_pinboard_authorizer_cb); + Py_VISIT(self->row_factory); + Py_VISIT(self->text_factory); + Py_VISIT(self->collations); + Py_VISIT(self->statements); + Py_VISIT(self->cursors); + Py_VISIT(Py_TYPE(self)); + return 0; +} + +static int +connection_clear(pysqlite_Connection *self) +{ + Py_CLEAR(self->statement_cache); + Py_CLEAR(self->isolation_level); + Py_CLEAR(self->function_pinboard_trace_callback); + Py_CLEAR(self->function_pinboard_progress_handler); + Py_CLEAR(self->function_pinboard_authorizer_cb); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->text_factory); + Py_CLEAR(self->collations); + Py_CLEAR(self->statements); + Py_CLEAR(self->cursors); + return 0; +} + static void -pysqlite_connection_dealloc(pysqlite_Connection *self) +connection_dealloc(pysqlite_Connection *self) { PyTypeObject *tp = Py_TYPE(self); - - Py_XDECREF(self->statement_cache); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); /* Clean up if user has not called .close() explicitly. */ if (self->db) { sqlite3_close_v2(self->db); } - Py_XDECREF(self->isolation_level); - Py_XDECREF(self->function_pinboard_trace_callback); - Py_XDECREF(self->function_pinboard_progress_handler); - Py_XDECREF(self->function_pinboard_authorizer_cb); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->text_factory); - Py_XDECREF(self->collations); - Py_XDECREF(self->statements); - Py_XDECREF(self->cursors); - tp->tp_free(self); Py_DECREF(tp); } @@ -1328,7 +1351,7 @@ pysqlite_connection_call(pysqlite_Connection *self, PyObject *args, _pysqlite_drop_unused_statement_references(self); - statement = PyObject_New(pysqlite_Statement, pysqlite_StatementType); + statement = PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType); if (!statement) { return NULL; } @@ -1909,21 +1932,22 @@ static struct PyMemberDef connection_members[] = }; static PyType_Slot connection_slots[] = { - {Py_tp_dealloc, pysqlite_connection_dealloc}, + {Py_tp_dealloc, connection_dealloc}, {Py_tp_doc, (void *)connection_doc}, {Py_tp_methods, connection_methods}, {Py_tp_members, connection_members}, {Py_tp_getset, connection_getset}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_connection_init}, {Py_tp_call, pysqlite_connection_call}, + {Py_tp_traverse, connection_traverse}, + {Py_tp_clear, connection_clear}, {0, NULL}, }; static PyType_Spec connection_spec = { .name = MODULE_NAME ".Connection", .basicsize = sizeof(pysqlite_Connection), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = connection_slots, }; diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c index b71f780..b3e1ce2 100644 --- a/Modules/_sqlite/cursor.c +++ b/Modules/_sqlite/cursor.c @@ -81,27 +81,46 @@ pysqlite_cursor_init_impl(pysqlite_Cursor *self, return 0; } -static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) +static int +cursor_traverse(pysqlite_Cursor *self, visitproc visit, void *arg) { - PyTypeObject *tp = Py_TYPE(self); + Py_VISIT(self->connection); + Py_VISIT(self->row_cast_map); + Py_VISIT(self->row_factory); + Py_VISIT(self->next_row); + Py_VISIT(Py_TYPE(self)); + return 0; +} +static int +cursor_clear(pysqlite_Cursor *self) +{ /* Reset the statement if the user has not closed the cursor */ if (self->statement) { pysqlite_statement_reset(self->statement); - Py_DECREF(self->statement); + Py_CLEAR(self->statement); } - Py_XDECREF(self->connection); - Py_XDECREF(self->row_cast_map); - Py_XDECREF(self->description); - Py_XDECREF(self->lastrowid); - Py_XDECREF(self->row_factory); - Py_XDECREF(self->next_row); + Py_CLEAR(self->connection); + Py_CLEAR(self->row_cast_map); + Py_CLEAR(self->description); + Py_CLEAR(self->lastrowid); + Py_CLEAR(self->row_factory); + Py_CLEAR(self->next_row); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} + +static void +cursor_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -487,7 +506,7 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* operation if (self->statement->in_use) { Py_SETREF(self->statement, - PyObject_New(pysqlite_Statement, pysqlite_StatementType)); + PyObject_GC_New(pysqlite_Statement, pysqlite_StatementType)); if (!self->statement) { goto error; } @@ -1006,21 +1025,22 @@ static const char cursor_doc[] = PyDoc_STR("SQLite database cursor class."); static PyType_Slot cursor_slots[] = { - {Py_tp_dealloc, pysqlite_cursor_dealloc}, + {Py_tp_dealloc, cursor_dealloc}, {Py_tp_doc, (void *)cursor_doc}, {Py_tp_iter, PyObject_SelfIter}, {Py_tp_iternext, pysqlite_cursor_iternext}, {Py_tp_methods, cursor_methods}, {Py_tp_members, cursor_members}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_cursor_init}, + {Py_tp_traverse, cursor_traverse}, + {Py_tp_clear, cursor_clear}, {0, NULL}, }; static PyType_Spec cursor_spec = { .name = MODULE_NAME ".Cursor", .basicsize = sizeof(pysqlite_Cursor), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = cursor_slots, }; diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 7d2d7ad..ece42f4 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -30,26 +30,33 @@ pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol *self, PyObject *args, return 0; } +static int +pysqlite_prepare_protocol_traverse(PyObject *self, visitproc visit, void *arg) +{ + Py_VISIT(Py_TYPE(self)); + return 0; +} + static void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol *self) { PyTypeObject *tp = Py_TYPE(self); - + PyObject_GC_UnTrack(self); tp->tp_free(self); Py_DECREF(tp); } static PyType_Slot type_slots[] = { {Py_tp_dealloc, pysqlite_prepare_protocol_dealloc}, - {Py_tp_new, PyType_GenericNew}, {Py_tp_init, pysqlite_prepare_protocol_init}, + {Py_tp_traverse, pysqlite_prepare_protocol_traverse}, {0, NULL}, }; static PyType_Spec type_spec = { .name = MODULE_NAME ".PrepareProtocol", .basicsize = sizeof(pysqlite_PrepareProtocol), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = type_slots, }; diff --git a/Modules/_sqlite/row.c b/Modules/_sqlite/row.c index f9dfcbd..af8be80 100644 --- a/Modules/_sqlite/row.c +++ b/Modules/_sqlite/row.c @@ -31,14 +31,29 @@ class _sqlite3.Row "pysqlite_Row *" "pysqlite_RowType" [clinic start generated code]*/ /*[clinic end generated code: output=da39a3ee5e6b4b0d input=384227da65f250fd]*/ -static void -pysqlite_row_dealloc(pysqlite_Row *self) +static int +row_clear(pysqlite_Row *self) { - PyTypeObject *tp = Py_TYPE(self); + Py_CLEAR(self->data); + Py_CLEAR(self->description); + return 0; +} - Py_XDECREF(self->data); - Py_XDECREF(self->description); +static int +row_traverse(pysqlite_Row *self, visitproc visit, void *arg) +{ + Py_VISIT(self->data); + Py_VISIT(self->description); + Py_VISIT(Py_TYPE(self)); + return 0; +} +static void +pysqlite_row_dealloc(PyObject *self) +{ + PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear(self); tp->tp_free(self); Py_DECREF(tp); } @@ -231,13 +246,15 @@ static PyType_Slot row_slots[] = { {Py_sq_length, pysqlite_row_length}, {Py_sq_item, pysqlite_row_item}, {Py_tp_new, pysqlite_row_new}, + {Py_tp_traverse, row_traverse}, + {Py_tp_clear, row_clear}, {0, NULL}, }; static PyType_Spec row_spec = { .name = MODULE_NAME ".Row", .basicsize = sizeof(pysqlite_Row), - .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, .slots = row_slots, }; diff --git a/Modules/_sqlite/statement.c b/Modules/_sqlite/statement.c index 5702627..3be12c7 100644 --- a/Modules/_sqlite/statement.c +++ b/Modules/_sqlite/statement.c @@ -369,26 +369,38 @@ void pysqlite_statement_mark_dirty(pysqlite_Statement* self) } static void -pysqlite_statement_dealloc(pysqlite_Statement *self) +stmt_dealloc(pysqlite_Statement *self) { PyTypeObject *tp = Py_TYPE(self); + PyObject_GC_UnTrack(self); + tp->tp_clear((PyObject *)self); + tp->tp_free(self); + Py_DECREF(tp); +} +static int +stmt_clear(pysqlite_Statement *self) +{ if (self->st) { Py_BEGIN_ALLOW_THREADS sqlite3_finalize(self->st); Py_END_ALLOW_THREADS + self->st = 0; } - self->st = NULL; - - Py_XDECREF(self->sql); - + Py_CLEAR(self->sql); if (self->in_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject*)self); } + return 0; +} - tp->tp_free(self); - Py_DECREF(tp); +static int +stmt_traverse(pysqlite_Statement *self, visitproc visit, void *arg) +{ + Py_VISIT(self->sql); + Py_VISIT(Py_TYPE(self)); + return 0; } /* @@ -467,15 +479,16 @@ static PyMemberDef stmt_members[] = { }; static PyType_Slot stmt_slots[] = { {Py_tp_members, stmt_members}, - {Py_tp_dealloc, pysqlite_statement_dealloc}, - {Py_tp_new, PyType_GenericNew}, + {Py_tp_dealloc, stmt_dealloc}, + {Py_tp_traverse, stmt_traverse}, + {Py_tp_clear, stmt_clear}, {0, NULL}, }; static PyType_Spec stmt_spec = { .name = MODULE_NAME ".Statement", .basicsize = sizeof(pysqlite_Statement), - .flags = Py_TPFLAGS_DEFAULT, + .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, .slots = stmt_slots, }; PyTypeObject *pysqlite_StatementType = NULL; |