Skip to content

Commit ca870ac

Browse files
author
Erlend E. Aasland
committed
sqlite3.Cache and sqlite3.Node types now implements GC protocol
1 parent 20da088 commit ca870ac

File tree

1 file changed

+57
-23
lines changed

1 file changed

+57
-23
lines changed

Modules/_sqlite/cache.c

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,27 @@ pysqlite_new_node(PyObject *key, PyObject *data)
4444
return node;
4545
}
4646

47+
static int
48+
node_traverse(pysqlite_Node *self, visitproc visit, void *arg)
49+
{
50+
Py_VISIT(Py_TYPE(self));
51+
return 0;
52+
}
53+
54+
static int
55+
node_clear(pysqlite_Node *self)
56+
{
57+
Py_CLEAR(self->key);
58+
Py_CLEAR(self->data);
59+
return 0;
60+
}
61+
4762
static void
4863
pysqlite_node_dealloc(pysqlite_Node *self)
4964
{
5065
PyTypeObject *tp = Py_TYPE(self);
51-
52-
Py_DECREF(self->key);
53-
Py_DECREF(self->data);
54-
66+
PyObject_GC_UnTrack(self);
67+
tp->tp_clear((PyObject *)self);
5568
tp->tp_free(self);
5669
Py_DECREF(tp);
5770
}
@@ -88,31 +101,50 @@ pysqlite_cache_init(pysqlite_Cache *self, PyObject *args, PyObject *kwargs)
88101
return 0;
89102
}
90103

91-
static void
92-
pysqlite_cache_dealloc(pysqlite_Cache *self)
104+
static int
105+
cache_traverse(pysqlite_Cache *self, visitproc visit, void *arg)
93106
{
94-
PyTypeObject *tp = Py_TYPE(self);
95-
pysqlite_Node* node;
96-
pysqlite_Node* delete_node;
97-
98-
if (!self->factory) {
99-
/* constructor failed, just get out of here */
100-
return;
107+
pysqlite_Node *node = self->first;
108+
while (node) {
109+
Py_VISIT(node);
110+
node = node->next;
101111
}
112+
Py_VISIT(self->mapping);
113+
if (self->decref_factory) {
114+
Py_VISIT(self->factory);
115+
}
116+
Py_VISIT(Py_TYPE(self));
117+
return 0;
118+
}
102119

120+
static int
121+
cache_clear(pysqlite_Cache *self)
122+
{
103123
/* iterate over all nodes and deallocate them */
104-
node = self->first;
124+
pysqlite_Node *node = self->first;
105125
while (node) {
106-
delete_node = node;
126+
pysqlite_Node *delete_node = node;
107127
node = node->next;
108-
Py_DECREF(delete_node);
128+
Py_CLEAR(delete_node);
109129
}
110-
111130
if (self->decref_factory) {
112-
Py_DECREF(self->factory);
131+
Py_CLEAR(self->factory);
132+
}
133+
Py_CLEAR(self->mapping);
134+
return 0;
135+
}
136+
137+
static void
138+
pysqlite_cache_dealloc(pysqlite_Cache *self)
139+
{
140+
if (!self->factory) {
141+
/* constructor failed, just get out of here */
142+
return;
113143
}
114-
Py_DECREF(self->mapping);
115144

145+
PyObject_GC_UnTrack(self);
146+
PyTypeObject *tp = Py_TYPE(self);
147+
tp->tp_clear((PyObject *)self);
116148
tp->tp_free(self);
117149
Py_DECREF(tp);
118150
}
@@ -260,14 +292,15 @@ pysqlite_cache_display(pysqlite_Cache *self, PyObject *args)
260292

261293
static PyType_Slot node_slots[] = {
262294
{Py_tp_dealloc, pysqlite_node_dealloc},
263-
{Py_tp_new, PyType_GenericNew},
295+
{Py_tp_traverse, node_traverse},
296+
{Py_tp_clear, node_clear},
264297
{0, NULL},
265298
};
266299

267300
static PyType_Spec node_spec = {
268301
.name = MODULE_NAME ".Node",
269302
.basicsize = sizeof(pysqlite_Node),
270-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
303+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
271304
.slots = node_slots,
272305
};
273306
PyTypeObject *pysqlite_NodeType = NULL;
@@ -283,15 +316,16 @@ static PyMethodDef cache_methods[] = {
283316
static PyType_Slot cache_slots[] = {
284317
{Py_tp_dealloc, pysqlite_cache_dealloc},
285318
{Py_tp_methods, cache_methods},
286-
{Py_tp_new, PyType_GenericNew},
287319
{Py_tp_init, pysqlite_cache_init},
320+
{Py_tp_traverse, cache_traverse},
321+
{Py_tp_clear, cache_clear},
288322
{0, NULL},
289323
};
290324

291325
static PyType_Spec cache_spec = {
292326
.name = MODULE_NAME ".Cache",
293327
.basicsize = sizeof(pysqlite_Cache),
294-
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
328+
.flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
295329
.slots = cache_slots,
296330
};
297331
PyTypeObject *pysqlite_CacheType = NULL;

0 commit comments

Comments
 (0)