]> granicus.if.org Git - python/commitdiff
Patch by Vladimir Marangoz to allow freeing of the allocated blocks of
authorGuido van Rossum <guido@python.org>
Wed, 10 Mar 1999 22:55:47 +0000 (22:55 +0000)
committerGuido van Rossum <guido@python.org>
Wed, 10 Mar 1999 22:55:47 +0000 (22:55 +0000)
floats on finalization.

Objects/floatobject.c

index 070e83def9af0ccf7fb14a0ce034763c54f80bca..f8da205d11f236f8e31e9d1e0b170f7a43accdb4 100644 (file)
@@ -95,20 +95,27 @@ double (*_Py_math_funcs_hack[])() = {
 
 /* Special free list -- see comments for same code in intobject.c. */
 static PyFloatObject *free_list = NULL;
+static PyFloatObject *block_list = NULL;
 #define BLOCK_SIZE     1000    /* 1K less typical malloc overhead */
-#define N_FLOATOBJECTS (BLOCK_SIZE / sizeof(PyFloatObject))
+#define N_FLOATOBJECTS ((BLOCK_SIZE - sizeof(PyFloatObject *)) / \
+                        sizeof(PyFloatObject))
+#define PyMem_MALLOC   malloc
+#define PyMem_FREE     free
 
 static PyFloatObject *
 fill_free_list()
 {
        PyFloatObject *p, *q;
-       p = PyMem_NEW(PyFloatObject, N_FLOATOBJECTS);
+       p = (PyFloatObject *)PyMem_MALLOC(BLOCK_SIZE);
        if (p == NULL)
                return (PyFloatObject *)PyErr_NoMemory();
+       *(PyFloatObject **)p = block_list;
+       block_list = p;
+       p = (PyFloatObject *)((char *)p + sizeof(PyFloatObject *));
        q = p + N_FLOATOBJECTS;
        while (--q > p)
-               *(PyFloatObject **)q = q-1;
-       *(PyFloatObject **)q = NULL;
+               q->ob_type = (struct _typeobject *)(q-1);
+       q->ob_type = NULL;
        return p + N_FLOATOBJECTS - 1;
 }
 
@@ -126,7 +133,7 @@ PyFloat_FromDouble(fval)
                        return NULL;
        }
        op = free_list;
-       free_list = *(PyFloatObject **)free_list;
+       free_list = (PyFloatObject *)op->ob_type;
        op->ob_type = &PyFloat_Type;
        op->ob_fval = fval;
        _Py_NewReference(op);
@@ -137,7 +144,7 @@ static void
 float_dealloc(op)
        PyFloatObject *op;
 {
-       *(PyFloatObject **)op = free_list;
+       op->ob_type = (struct _typeobject *)free_list;
        free_list = op;
 }
 
@@ -604,5 +611,47 @@ PyTypeObject PyFloat_Type = {
 void
 PyFloat_Fini()
 {
-       /* XXX Alas, the free list is not easily and safely freeable */
+       PyFloatObject *p, *list;
+       int i;
+       int bc, bf;     /* block count, number of freed blocks */
+       int frem, fsum; /* remaining unfreed floats per block, total */
+
+       bc = 0;
+       bf = 0;
+       fsum = 0;
+       list = block_list;
+       block_list = NULL;
+       while (list != NULL) {
+               p = list;
+               p = (PyFloatObject *)((char *)p + sizeof(PyFloatObject *));
+               bc++;
+               frem = 0;
+               for (i = 0; i < N_FLOATOBJECTS; i++, p++) {
+                       if (PyFloat_Check(p) && p->ob_refcnt != 0)
+                               frem++;
+               }
+               p = list;
+               list = *(PyFloatObject **)p;
+               if (frem) {
+                       *(PyFloatObject **)p = block_list;
+                       block_list = p;
+               }
+               else {
+                       PyMem_FREE(p);
+                       bf++;
+               }
+               fsum += frem;
+       }
+       if (Py_VerboseFlag) {
+               fprintf(stderr, "# cleanup floats");
+               if (!fsum) {
+                       fprintf(stderr, "\n");
+               }
+               else {
+                       fprintf(stderr,
+                           ": %d unfreed float%s in %d out of %d block%s\n",
+                               fsum, fsum == 1 ? "" : "s",
+                               bc - bf, bc, bc == 1 ? "" : "s");
+               }
+       }
 }