In perl, the designer of an API must consider which are the "root objects" that they want a user to hold onto, and all objects should have a tree of ownership from those root objects that determines when they get freed. If one of your internal "leaf" objects needs to refer back to a root object, use a weakened reference.
Consider the actual filesystem: In Unix, each file and directory have a "link count". A directory has one reference to itself ("."), one reference to the parent (".."), and one reference to each file or subdirectory. Stated the other way around, the references to a directory are one from the parent, one from itself, and one from each subdirectory. A file (inode) has one link from each directory it is listed in, but no references outward. You cannot determine the directory of a file from just the file inode. In Unix, the directory tree is global, and a directory may not be removed from the tree unless it is empty. This is because Unix doesn't have weak-references and the only way it can know that all the subdirectories got cleaned up is if you first empty each one of them and remove it from the parent.
Now consider how things could work if Unix did have weak-references. Each directory could use a weak-reference for ".." and ".", and so the subdirectories would not be adding to the link count for a directory. The directory would have a link count of exactly 1 for as long as it was referenced by the parent. You would be able to "rm" ("unlink") a directory and then let the filesystem driver delete it in the background asynchronously. Each time the directory got deleted, the filesystem driver would reduce the link count of all the files and directories under it, and then continue to free those if their count dropped to 0. If the system rebooted, the filesystem driver would be able to pick up where it left off by checking the link counts of remaining directories.
The first case works because the kernel can enforce the policy of making sure a directory is empty before allowing it to be removed from the tree, and because the root of the tree is global (the reference won't get lost by going out of scope of some function). In a perl program, you could mimic this with an API that enforces directories be empty before removing them from the tree, and have the root directory referenced from a package global. This would work and not leak memory and you would get exactly the same semantics as the real filesystem. You could also opt to let files refer to their directory, but no longer list them in more than one directory.
If you didn't want your perl-object-filesystem to be global, you need something more like the second design. You need a way to know when *all* application references to the tree have been dropped so that you can clean up the entire tree. There are actually several ways to do it. The simplest is to make each "forward" reference from directory to its content "strong", and each "backward" reference from content to containing directory "weak". If you have a reference to a directory and drop the reference to the tree leading up to it, the directory suddenly becomes the root of the remaining tree. A second way is to have the whole tree be strongly-linked in both directions, but then don't let the user hold onto the internal objects. Instead, give the user "proxy" objects that hold a strong reference to parts of the tree, and manage your own reference count stored somewhere in the tree. When the last proxy object is garbage collected, your DESTROY method decreases the manual reference count on the tree and sees that it was the last proxy object, then walks the entire tree breaking all the references. This would be sort of like lazy-unmounting a filesystem when the last open handle was closed.
Back to your original question, if you just ignore the whole topic and create circular strong references without a plan to clean it up, then every time you make temporary usage of your API you will reserve some more memory and never get it back until the program exits. That is bad for long-lived processes like web servers, and even sometimes for batch processing if you need a bunch of temporary calculations. Other batch processing will be fine; it creates objects for the input data, and then the whole process exits freeing everything anyway.
In reply to Re: Should I use weaken on an object attribute containing a reference to an object which contains reference back to original object?
by NERDVANA
in thread Should I use weaken on an object attribute containing a reference to an object which contains reference back to original object?
by nysus
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |