Learning Perl Objects, References amp;amp; Modules [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Learning Perl Objects, References amp;amp; Modules [Electronic resources] - نسخه متنی

Randal L. Schwartz

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید














10.6 Weakening the Argument


The %REGISTRY
variable also holds a reference to each animal. So even if you toss
away the containing variables:

{
my @cows = map Cow->named($_), qw(Bessie Gwen);
my @horses = map Horse->named($_), ("Trigger", "Mr. Ed");
my @racehorses = RaceHorse->named("Billy Boy");
}
print "We've seen:\n", map(" $_\n", Animal->registered);
print "End of program.\n";

you'll still see the same result. The animals
aren't destroyed even though none of the code is
holding the animals. At first glance, it looks like you can fix this
by altering the destructor:

## in Animal
sub DESTROY {
my $self = shift;
print "[", $self->name, " has died.]\n";
delete $REGISTRY{$self};
}

But this still results in the same output.
Why? Because the destructor isn't called until the
last reference is gone, but the last reference won't
be destroyed until the destructor is called.[10]

[10] We'd make a reference to chickens and eggs,
but that would introduce yet another derived class to
Animal.


One solution for fairly recent
Perl versions[11] is to
use weak references. A weak reference is a
reference that doesn't count as far as the reference
counting, uh, counts. It's best illustrated by
example.

[11] 5.6 and later.


The weak
reference mechanism is already built into the core of recent Perl
versions, but as of this writing, the user interface is still
accessed by a CPAN module called WeakRef. After
installing this module,Chapter 15 for information on installing modules.


## in Animal
use WeakRef qw(weaken); ## new
sub named {
ref(my $class = shift) and croak "class only";
my $name = shift;
my $self = { Name => $name, Color => $class->default_color };
bless $self, $class;
$REGISTRY{$self} = $self;
weaken($REGISTRY{$self});
$self;
}

When Perl counts the number of active references to a
thingy,[13] it
won't count any that have been converted to weak
references by weaken. If all ordinary references
are gone, Perl deletes the thingy and turns any weak references to
undef.

[13] A thingy as defined in
Perl's own documentation, is anything a reference
points to, such as an object. If you are an especially boring person,
you could call it a referent instead.


Now you'll get the right behavior for:

my @horses = map Horse->named($_), ("Trigger", "Mr. Ed");
print "alive before block:\n", map(" $_\n", Animal->registered);
{
my @cows = map Cow->named($_), qw(Bessie Gwen);
my @racehorses = RaceHorse->named("Billy Boy");
print "alive inside block:\n", map(" $_\n", Animal->registered);
}
print "alive after block:\n", map(" $_\n", Animal->registered);
print "End of program.\n";

This prints:

alive before block:
a Horse named Trigger
a Horse named Mr. Ed
alive inside block:
a RaceHorse named Billy Boy
a Cow named Gwen
a Horse named Trigger
a Horse named Mr. Ed
a Cow named Bessie
[Billy Boy has died.]
[Billy Boy has gone off to the glue factory.]
[Gwen has died.]
[Bessie has died.]
alive after block:
a Horse named Trigger
a Horse named Mr. Ed
End of program.
[Mr. Ed has died.]
[Mr. Ed has gone off to the glue factory.]
[Trigger has died.]
[Trigger has gone off to the glue factory.]

Notice that the racehorses and cows die at the end of the block, but
the ordinary horses die at the end of the program. Success!

Weak
references can also solve some memory leak issues. For example,
suppose an animal wanted to record its pedigree. The parents might
want to hold references to all their children while each child might
want to hold references to each parent.

One or the other (or even both) of these
links can be weakened. If the link to the child is weakened, the
child can be destroyed when all other references are lost, and the
parent's link simply becomes
undef (or you can set a destructor to completely
remove it). However, a parent won't disappear as
long as it still has offspring. Similarly, if the link to the parent
is weakened, you'll simply get it as
undef when the parent is no longer referenced by
other data structures. It's really quite
flexible.[14]

[14] When using weak references, always make
sure you don't dereference a weakened reference that
has turned to undef.


Without weakening, as soon as any
parent-child relationship is created, both the parent and the child
remain in memory until the final global destruction phase, regardless
of the destruction of the other structures holding either the parent
or the child.

Be aware though: weak references should be used carefully, not just
thrown at a problem of circular references. If you destroy data that
is held by a weak reference before its time, you may have some very
confusing programming problems to solve and debug.


/ 199