Re: Unbalanced string table refcount (was: perl@15930)
Nicholas Clark [Tue, 16 Apr 2002 22:22:41 +0000 (23:22 +0100)]
Message-ID: <20020416212241.GA315@Bagpuss.unfortu.net>

p4raw-id: //depot/perl@15958

embed.fnc
global.sym
hv.c
universal.c

index 20517df..45c9d96 100644 (file)
--- a/embed.fnc
+++ b/embed.fnc
@@ -278,7 +278,7 @@ Apd |char*  |hv_iterkey     |HE* entry|I32* retlen
 Apd    |SV*    |hv_iterkeysv   |HE* entry
 Apd    |HE*    |hv_iternext    |HV* tb
 Apd    |SV*    |hv_iternextsv  |HV* hv|char** key|I32* retlen
-ApM    |HE*    |hv_iternext_flags|HV* tb|I32 flags
+ApMd   |HE*    |hv_iternext_flags|HV* tb|I32 flags
 Apd    |SV*    |hv_iterval     |HV* tb|HE* entry
 Ap     |void   |hv_ksplit      |HV* hv|IV newmax
 Apd    |void   |hv_magic       |HV* hv|GV* gv|int how
index cc4d2a1..dec0480 100644 (file)
@@ -208,6 +208,7 @@ Perl_is_utf8_string
 Perl_is_utf8_alnum
 Perl_is_utf8_alnumc
 Perl_is_utf8_idfirst
+Perl_is_utf8_idcont
 Perl_is_utf8_alpha
 Perl_is_utf8_ascii
 Perl_is_utf8_space
diff --git a/hv.c b/hv.c
index 51f47fd..02a0955 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -1758,6 +1758,14 @@ Perl_hv_iterinit(pTHX_ HV *hv)
 
 Returns entries from a hash iterator.  See C<hv_iterinit>.
 
+You may call C<hv_delete> or C<hv_delete_ent> on the hash entry that the
+iterator currently points to, without losing your place or invalidating your
+iterator.  Note that in this case the current entry is deleted from the hash
+with your iterator holding the last reference to it.  Your iterator is flagged
+to free the entry on the next call to C<hv_iternext>, so you must not discard
+your iterator immediately else the entry will leak - call C<hv_iternext> to
+trigger the resource deallocation.
+
 =cut
 */
 
@@ -1768,11 +1776,19 @@ Perl_hv_iternext(pTHX_ HV *hv)
 }
 
 /*
-XXX=for apidoc hv_iternext
-
-Returns entries from a hash iterator.  See C<hv_iterinit>.
+=for apidoc hv_iternext_flags
+
+Returns entries from a hash iterator.  See C<hv_iterinit> and C<hv_iternext>.
+The C<flags> value will normally be zero; if HV_ITERNEXT_WANTPLACEHOLDERS is
+set the placeholders keys (for restricted hashes) will be returned in addition
+to normal keys. By default placeholders are automatically skipped over.
+Currently a placeholder is implemented with a value that is literally
+<&Perl_sv_undef> (a regular C<undef> value is a normal read-write SV for which
+C<!SvOK> is false). Note that the implementation of placeholders and
+restricted hashes may change, and the implementation currently is
+insufficiently abstracted for any change to be tidy.
 
-XXX=cut
+=cut
 */
 
 HE *
index 550ea4d..926d1c3 100644 (file)
@@ -520,9 +520,16 @@ XS(XS_Internals_hv_clear_placehold)
         I32 riter = HvRITER(hv);
         HE *eiter = HvEITER(hv);
         hv_iterinit(hv);
-        while (items
-               && (entry
-                   = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))) {
+        /* This may look suboptimal with the items *after* the iternext, but
+           it's quite deliberate. We only get here with items==0 if we've
+           just deleted the last placeholder in the hash. If we've just done
+           that then it means that the hash is in lazy delete mode, and the
+           HE is now only referenced in our iterator. If we just quit the loop
+           and discarded our iterator then the HE leaks. So we do the && the
+           other way to ensure iternext is called just one more time, which
+           has the side effect of triggering the lazy delete.  */
+        while ((entry = hv_iternext_flags(hv, HV_ITERNEXT_WANTPLACEHOLDERS))
+            && items) {
             SV *val = hv_iterval(hv, entry);
 
             if (val == &PL_sv_undef) {