Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Perl, why does copying a weak reference create a normal, strong, reference?

Scalar::Util::weaken says:

NOTE: Copying a weak reference creates a normal, strong, reference.

I can't understand why Perl handle it this way. In my applications, I use weaken to break cycles. Sometimes i have to weaken references that would be already weak if Perl wouldn't act this way.

like image 754
key_ Avatar asked Dec 16 '10 18:12

key_


People also ask

What is the difference between strong and weak references?

Anytime a pointer variable points to an object, that object has an owner and will stay alive. This is known as a strong reference. A variable can optionally not take ownership of an object that it points to. A variable that does not take ownership of an object is known as a weak reference.

How do weak references work?

A Weak reference is a reference that does not protect a referenced object from collection by GC. i.e. garbage collects when no Strong or Soft refs. A Phantom reference is a reference to an object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed.

Should I always use weak references?

According to Apple's docs: “Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization.”

What is strong reference and weak reference in Objective C?

A reference to an object is any object pointer or property that lets you reach the object. There are two types of object reference: Strong references, which keep an object “alive” in memory. Weak references, which have no effect on the lifetime of a referenced object.


2 Answers

Any time you copy a reference into a new variable, the reference count is incremented. This is true when copying a weak or strong reference.

my $obj = {};    # 1 reference to {} stored in $obj

my $copy = $obj; # 2 references

weaken $obj;     # 1 reference

at this point, if $copy goes out of scope, the reference count will fall to zero, and the memory will be freed. Now assume the following code:

my $newref = $obj;  # 2 references

undef $copy;        # 1 reference

If Perl preserved the weak reference in $newref, then the hash would be unexpectedly dealocated when $copy was cleared. This would break the expectation that when you copy a reference, it will at least stick around as long as the copy.

In short, if weak references persisted across an assignment, it would force you to litter your code with myriad weakness checks, and would require some other way to unweaken a variable, all to avoid the inevitable variable suicide issues.

like image 161
Eric Strom Avatar answered Nov 15 '22 16:11

Eric Strom


I think this is an encapsulation issue. If a third party library uses weak refs internally my code should not be expected to know ahead of time that when I make a copy of a reference that it might suddenly disappear on me. The usual expectation in Perl is that a ref will remain valid as long as it exists. When you call weaken you basically have promised that you will take the needed steps to check that the reference is still valid before you use it.

As a second reason the interface to weaken a strong copy of a weak ref is fairly strait forward.

my $new_ref = $old_ref; if (isweak($old_ref)) { weaken($new_ref); }

The code to do the same to get a strong ref if a weak ref created a weak ref is a bit more complicated.

my $new_ref;
if (ref($old_ref) eq 'ARRAY') {
    $new_ref = \@{$old_ref};
}
elsif (ref($old_ref) eq 'HASH') {
    $new_ref = \%{$old_ref};
}
elsif (.....

If you know the ref can only be one type you can save the if/elsif cascade and simply do the deref-reref, but it's still harder to judge why you dereferenced just to take a new reference. The next maintainer will try to 'fix' your code.

like image 42
Ven'Tatsu Avatar answered Nov 15 '22 17:11

Ven'Tatsu