Subject: | weak_ref bug/enhancement |
Date: | Fri, 15 Jun 2018 15:44:29 +0000 |
To: | "bug-Moo [...] rt.cpan.org" <bug-Moo [...] rt.cpan.org> |
From: | "Hugo van der Sanden, Pirum" <hugo.vandersanden [...] pirum.com> |
I'm not sure if this is a bug report or an enhancement request. The current implementation of weak_ref comes in the main case from this chunk of Method::Generate::Accessor:
my $weak_simple = _CAN_WEAKEN_READONLY
? "do { Scalar::Util::weaken(${simple}); no warnings 'void'; $get }"
.. which in the main case expands to roughly:
"do { Scalar::Util::weaken(${me}->{${name_str}} = ${value}); no warnings 'void'; ${me}->{${name_str}} }"
This has suboptimal behaviour when the ${value} is not guaranteed already to have additional refs - because the only reference is weakened before being returned, so we just get undef back.
It would need a bit of refactoring, but if it could be changed to something like:
"do { my \$hard_ref = ${value}; Scalar::Util::weaken(${me}->{${name_str}} = \$hard_ref); no warnings 'void'; \$hard_ref }"
.. then we'd return the calculated value, and it would survive at least as long as the caller kept hold of it. (Even better would be if freeing of the weakref could cause the builder to be reinvoked on next access; I've not yet looked to see if that would happen, or if it would be hard to add.)
I want this for a case where instances in two classes have lazy references to each other, and I need to break the reference loop. Where I've used weak_ref in previous such cases I've been able to guarantee the dominant ref is held before the subordinate one is generated, but I don't currently have a good workaround in this case.
Hugo