From: Dave Mitchell Date: Thu, 21 Aug 2008 00:02:57 +0000 (+0000) Subject: better document how the weakref backrefs array is refcounted X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=fd996479e27a404cbaed7b3ad029feb14440afb0;p=p5sagit%2Fp5-mst-13.2.git better document how the weakref backrefs array is refcounted p4raw-id: //depot/perl@34211 --- diff --git a/sv.c b/sv.c index 6957382..f721e6f 100644 --- a/sv.c +++ b/sv.c @@ -5007,6 +5007,24 @@ Perl_sv_rvweaken(pTHX_ SV *const sv) * back-reference to sv onto the array associated with the backref magic. */ +/* A discussion about the backreferences array and its refcount: + * + * The AV holding the backreferences is pointed to either as the mg_obj of + * PERL_MAGIC_backref, or in the specific case of a HV that has the hv_aux + * structure, from the xhv_backreferences field. (A HV without hv_aux will + * have the standard magic instead.) The array is created with a refcount + * of 2. This means that if during global destruction the array gets + * picked on first to have its refcount decremented by the random zapper, + * it won't actually be freed, meaning it's still theere for when its + * parent gets freed. + * When the parent SV is freed, in the case of magic, the magic is freed, + * Perl_magic_killbackrefs is called which decrements one refcount, then + * mg_obj is freed which kills the second count. + * In the vase of a HV being freed, one ref is removed by + * Perl_hv_kill_backrefs, the other by Perl_sv_kill_backrefs, which it + * calls. + */ + void Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv) { @@ -5035,7 +5053,7 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv) } else { av = newAV(); AvREAL_off(av); - SvREFCNT_inc_simple_void(av); + SvREFCNT_inc_simple_void(av); /* see discussion above */ } *avp = av; } @@ -5048,9 +5066,7 @@ Perl_sv_add_backref(pTHX_ SV *const tsv, SV *const sv) av = newAV(); AvREAL_off(av); sv_magic(tsv, (SV*)av, PERL_MAGIC_backref, NULL, 0); - /* av now has a refcnt of 2, which avoids it getting freed - * before us during global cleanup. The extra ref is removed - * by magic_killbackrefs() when tsv is being freed */ + /* av now has a refcnt of 2; see discussion above */ } } if (AvFILLp(av) >= AvMAX(av)) {