@@ -30,6 +30,7 @@ static PyTypeObject tuplegetter_type;
30
30
31
31
#define BLOCKLEN 64
32
32
#define CENTER ((BLOCKLEN - 1) / 2)
33
+ #define MAXFREEBLOCKS 16
33
34
34
35
/* Data for deque objects is stored in a doubly-linked list of fixed
35
36
* length blocks. This assures that appends or pops never move any
@@ -92,6 +93,8 @@ typedef struct {
92
93
Py_ssize_t rightindex ; /* 0 <= rightindex < BLOCKLEN */
93
94
size_t state ; /* incremented whenever the indices move */
94
95
Py_ssize_t maxlen ; /* maxlen is -1 for unbounded deques */
96
+ Py_ssize_t numfreeblocks ;
97
+ block * freeblocks [MAXFREEBLOCKS ];
95
98
PyObject * weakreflist ;
96
99
} dequeobject ;
97
100
@@ -123,16 +126,12 @@ static PyTypeObject deque_type;
123
126
added at about the same rate as old blocks are being freed.
124
127
*/
125
128
126
- #define MAXFREEBLOCKS 16
127
- static Py_ssize_t numfreeblocks = 0 ;
128
- static block * freeblocks [MAXFREEBLOCKS ];
129
-
130
- static block *
131
- newblock (void ) {
129
+ static inline block *
130
+ newblock (dequeobject * deque ) {
132
131
block * b ;
133
- if (numfreeblocks ) {
134
- numfreeblocks -- ;
135
- return freeblocks [numfreeblocks ];
132
+ if (deque -> numfreeblocks ) {
133
+ deque -> numfreeblocks -- ;
134
+ return deque -> freeblocks [deque -> numfreeblocks ];
136
135
}
137
136
b = PyMem_Malloc (sizeof (block ));
138
137
if (b != NULL ) {
@@ -142,12 +141,12 @@ newblock(void) {
142
141
return NULL ;
143
142
}
144
143
145
- static void
146
- freeblock (block * b )
144
+ static inline void
145
+ freeblock (dequeobject * deque , block * b )
147
146
{
148
- if (numfreeblocks < MAXFREEBLOCKS ) {
149
- freeblocks [numfreeblocks ] = b ;
150
- numfreeblocks ++ ;
147
+ if (deque -> numfreeblocks < MAXFREEBLOCKS ) {
148
+ deque -> freeblocks [deque -> numfreeblocks ] = b ;
149
+ deque -> numfreeblocks ++ ;
151
150
} else {
152
151
PyMem_Free (b );
153
152
}
@@ -164,7 +163,7 @@ deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
164
163
if (deque == NULL )
165
164
return NULL ;
166
165
167
- b = newblock ();
166
+ b = newblock (deque );
168
167
if (b == NULL ) {
169
168
Py_DECREF (deque );
170
169
return NULL ;
@@ -180,6 +179,7 @@ deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
180
179
deque -> rightindex = CENTER ;
181
180
deque -> state = 0 ;
182
181
deque -> maxlen = -1 ;
182
+ deque -> numfreeblocks = 0 ;
183
183
deque -> weakreflist = NULL ;
184
184
185
185
return (PyObject * )deque ;
@@ -204,7 +204,7 @@ deque_pop(dequeobject *deque, PyObject *unused)
204
204
if (Py_SIZE (deque )) {
205
205
prevblock = deque -> rightblock -> leftlink ;
206
206
assert (deque -> leftblock != deque -> rightblock );
207
- freeblock (deque -> rightblock );
207
+ freeblock (deque , deque -> rightblock );
208
208
CHECK_NOT_END (prevblock );
209
209
MARK_END (prevblock -> rightlink );
210
210
deque -> rightblock = prevblock ;
@@ -242,7 +242,7 @@ deque_popleft(dequeobject *deque, PyObject *unused)
242
242
if (Py_SIZE (deque )) {
243
243
assert (deque -> leftblock != deque -> rightblock );
244
244
prevblock = deque -> leftblock -> rightlink ;
245
- freeblock (deque -> leftblock );
245
+ freeblock (deque , deque -> leftblock );
246
246
CHECK_NOT_END (prevblock );
247
247
MARK_END (prevblock -> leftlink );
248
248
deque -> leftblock = prevblock ;
@@ -278,7 +278,7 @@ static inline int
278
278
deque_append_internal (dequeobject * deque , PyObject * item , Py_ssize_t maxlen )
279
279
{
280
280
if (deque -> rightindex == BLOCKLEN - 1 ) {
281
- block * b = newblock ();
281
+ block * b = newblock (deque );
282
282
if (b == NULL )
283
283
return -1 ;
284
284
b -> leftlink = deque -> rightblock ;
@@ -315,7 +315,7 @@ static inline int
315
315
deque_appendleft_internal (dequeobject * deque , PyObject * item , Py_ssize_t maxlen )
316
316
{
317
317
if (deque -> leftindex == 0 ) {
318
- block * b = newblock ();
318
+ block * b = newblock (deque );
319
319
if (b == NULL )
320
320
return -1 ;
321
321
b -> rightlink = deque -> leftblock ;
@@ -584,7 +584,7 @@ deque_clear(dequeobject *deque)
584
584
adversary could cause it to never terminate).
585
585
*/
586
586
587
- b = newblock ();
587
+ b = newblock (deque );
588
588
if (b == NULL ) {
589
589
PyErr_Clear ();
590
590
goto alternate_method ;
@@ -623,13 +623,13 @@ deque_clear(dequeobject *deque)
623
623
itemptr = leftblock -> data ;
624
624
limit = itemptr + m ;
625
625
n -= m ;
626
- freeblock (prevblock );
626
+ freeblock (deque , prevblock );
627
627
}
628
628
item = * (itemptr ++ );
629
629
Py_DECREF (item );
630
630
}
631
631
CHECK_END (leftblock -> rightlink );
632
- freeblock (leftblock );
632
+ freeblock (deque , leftblock );
633
633
return 0 ;
634
634
635
635
alternate_method :
@@ -679,7 +679,7 @@ deque_inplace_repeat(dequeobject *deque, Py_ssize_t n)
679
679
deque -> state ++ ;
680
680
for (i = 0 ; i < n - 1 ; ) {
681
681
if (deque -> rightindex == BLOCKLEN - 1 ) {
682
- block * b = newblock ();
682
+ block * b = newblock (deque );
683
683
if (b == NULL ) {
684
684
Py_SET_SIZE (deque , Py_SIZE (deque ) + i );
685
685
return NULL ;
@@ -797,7 +797,7 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n)
797
797
while (n > 0 ) {
798
798
if (leftindex == 0 ) {
799
799
if (b == NULL ) {
800
- b = newblock ();
800
+ b = newblock (deque );
801
801
if (b == NULL )
802
802
goto done ;
803
803
}
@@ -841,7 +841,7 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n)
841
841
while (n < 0 ) {
842
842
if (rightindex == BLOCKLEN - 1 ) {
843
843
if (b == NULL ) {
844
- b = newblock ();
844
+ b = newblock (deque );
845
845
if (b == NULL )
846
846
goto done ;
847
847
}
@@ -885,7 +885,7 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n)
885
885
rv = 0 ;
886
886
done :
887
887
if (b != NULL )
888
- freeblock (b );
888
+ freeblock (deque , b );
889
889
deque -> leftblock = leftblock ;
890
890
deque -> rightblock = rightblock ;
891
891
deque -> leftindex = leftindex ;
@@ -1306,16 +1306,21 @@ deque_ass_item(dequeobject *deque, Py_ssize_t i, PyObject *v)
1306
1306
static void
1307
1307
deque_dealloc (dequeobject * deque )
1308
1308
{
1309
+ Py_ssize_t i ;
1310
+
1309
1311
PyObject_GC_UnTrack (deque );
1310
1312
if (deque -> weakreflist != NULL )
1311
1313
PyObject_ClearWeakRefs ((PyObject * ) deque );
1312
1314
if (deque -> leftblock != NULL ) {
1313
1315
deque_clear (deque );
1314
1316
assert (deque -> leftblock != NULL );
1315
- freeblock (deque -> leftblock );
1317
+ freeblock (deque , deque -> leftblock );
1316
1318
}
1317
1319
deque -> leftblock = NULL ;
1318
1320
deque -> rightblock = NULL ;
1321
+ for (i = 0 ; i < deque -> numfreeblocks ; i ++ ) {
1322
+ PyMem_Free (deque -> freeblocks [i ]);
1323
+ }
1319
1324
Py_TYPE (deque )-> tp_free (deque );
1320
1325
}
1321
1326
0 commit comments