His example was more useful than the "foo" class above, but this shows the basic idea. The actual objects are held in a dataspace lexically scoped to the package, and is inaccessible outside the package. Outside the package, all the rest of the world gets is a blessed handle to the data locked away in the package, and can't see anything to directly manipulate.package Foo; { my @foos; sub new { push @foos,{ name => $_[1] }; my $obj = $#foos; return bless \$obj, $_[0]; } sub getname { return $foos[${$_[0]}]->{name}; } }
There does seem to be some limitations to this approach (such as difficulty doing inheritance, etc), but the one major question I have is with GC.
The actual objects are referred to by the array @foos, and only the array @foos. When the blessed handle goes out of scope, the object won't be cleaned up, because it is still being referred to by @foos. Only when the program exits will the object itself be cleaned. This could be a problem.
The obvious solution would be to add something like:
to the Foo class. Then, when the handle goes out of scope, Foo::DESTROY gets called, and all is well.sub DESTROY { $foos[${$_[0]}] = undef; }
What I'm concerned about is cases where the handle gets copied before it goes out of scope:
At the end of usesfoo, $foo falls out of scope. Is Perl smart enough to not call DESTROY $foo at that point, or will the copy of $foo saved in the return value be rendered useless?sub usesfoo { my ($name,$population) = @_; my $foo = new Foo($name); my %ret = { name => $name, pop => $population, foo => $foo }; return \%ret; }
Damian Conway's example does not include a destructor, so I can't tell by his example -- his looks to me like it leaks memory.
In reply to Flyweight Objects and garbage collection by BlaisePascal
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |