2009.11.29 - last edit >> Sun, 29 Nov 2009 13:55:22 -0500
When Standard Commenting Isn't Enough
I modified a matrix to handle (and reuse) its own memory. For example, when a
matrix is created to be a subsection of another one, the submatrix can use its
super's matrix elements. (super/sub =~ parent/child)
But there are some interesting dynamics at play. The submatrix may persist
(case 2) longer than its super, and should be responsible (case 4) for
cleaning up the memory, allowing the programmer to free up variable count and
write less cluttered code. Likewise, if there's a chain of the super/sub
relation and a middle one becomes useless (case 1), it can free the memory for
its "row" variable (of type number**, an array of pointers to beginnings of
rows). If there are no such links (case 3), all memory can go! (elements,
rows, and its own malloc'd space).
In case 2, the super's row data cannot be freed, since it also points to the
head of the element memory, whose location must clearly be known in order to
be freed.
That can get confusing... and for the system to be implemented correctly, the
programmer must have a strong understanding of the essential routines. A
standard commenting scheme just wouldn't cut it this time...
void cleanup_matrix (struct matrix* A)
{
assert (A);
assert (A->refc > 0);
-- A->refc;
if (mrefc_matrix (A)) return;
/* When I get older, */
if ( A->super && A->subc)
{
/* Losin' my rows, */
free_rows_matrix (A);
/* Many cycles through */
return;
}
/* Will you still be visiting my indices, */
if (! A->super && A->subc)
/* When I can reach malloc'd memory? */
return;
/* If I am left without any links, */
if (! A->super && ! A->subc)
{
free_elems_matrix (A);
free_rows_matrix (A);
free_matrix (A);
return;
}
/* Would I ever know? */
if ( A->super && ! A->subc)
{
/* Will you still need me, */
A->super->subc -= 1;
if (! A->super->subc)
/* Will you still free me, */
cleanup_matrix (A->super);
free_rows_matrix (A);
free_matrix (A);
return;
}
/* When I'm out of scope? */
}
For those interested, the memory isn't always freed - the matrix struct has
booleans freep (not on stack) and deepfreep (row/element data should be freed,
they will not be reused). There is also a constp data member, for when the
matrix elements should not be modified. This is useful for the programmer to
specify if the result of, say, a Gaussian elimination, is needed or if the
initial matrix state will be used as well.
-- Alex