First, I added a different mechanism for a Cell to refer back to
the Sheet without needing a strong or even weak reference, by
"registering" active sheets in a global hash by their address.
The global registry gets cleaned up as the objects go out of scope.
This also helps with Data::Dumper type things where someone might
dump the Cell object and not want to see the whole worksheet of
a million cells dumped at them.
Then, while debugging the unit test, I discovered that XML::Twig
objects were holding onto the Worksheet objects. I fixed that by
weakening the references to the sheet used in the XML::Twig
callbacks.
There is a final even more strange case where a XML::Twig object
doesn't get cleaned up until after the next XML::Twig object is
created. This leaves one XML object dangling at all times, but is
relatively harmless since they don't accumulate. I left a TODO in
the unit test for that problem.
First, I added a different mechanism for a Cell to refer back to the Sheet without needing a strong or even weak reference, by "registering" active sheets in a global hash by their address. The global registry gets cleaned up as the objects go out of scope. This also helps with Data::Dumper type things where someone might dump the Cell object and not want to see the whole worksheet of a million cells dumped at them.
Then, while debugging the unit test, I discovered that XML::Twig objects were holding onto the Worksheet objects. I fixed that by weakening the references to the sheet used in the XML::Twig callbacks.
There is a final even more strange case where a XML::Twig object doesn't get cleaned up until after the next XML::Twig object is created. This leaves one XML object dangling at all times, but is relatively harmless since they don't accumulate. I left a TODO in the unit test for that problem.