diff options
author | Nicholas Clark <nick@ccl4.org> | 2004-02-07 19:50:10 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2004-02-07 19:50:10 +0000 |
commit | d36773897a6f30fc5c947e9ed9a2e06b2e7f3b74 (patch) | |
tree | fefa6379d3daebd952da8a0c02f8bc254fc2a3cb /hv.c | |
parent | b6d030a4aa9e580b4848a75b15ef554dd4eca130 (diff) | |
download | perl-d36773897a6f30fc5c947e9ed9a2e06b2e7f3b74.tar.gz |
hv_clear_placeholders now manipulates the linked lists directly, rather
than using the iterator interface and calling hv_delete
This will allow hv_delete to be simplified to remove most of the
special casing related to placeholders.
p4raw-id: //depot/perl@22278
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 75 |
1 files changed, 39 insertions, 36 deletions
@@ -1495,42 +1495,45 @@ See Hash::Util::lock_keys() for an example of its use. void Perl_hv_clear_placeholders(pTHX_ HV *hv) { - I32 items; - items = (I32)HvPLACEHOLDERS(hv); - if (items) { - HE *entry; - I32 riter = HvRITER(hv); - HE *eiter = HvEITER(hv); - hv_iterinit(hv); - /* 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_placeholder) { - - /* It seems that I have to go back in the front of the hash - API to delete a hash, even though I have a HE structure - pointing to the very entry I want to delete, and could hold - onto the previous HE that points to it. And it's easier to - go in with SVs as I can then specify the precomputed hash, - and don't have fun and games with utf8 keys. */ - SV *key = hv_iterkeysv(entry); - - hv_delete_ent (hv, key, G_DISCARD, HeHASH(entry)); - items--; - } - } - HvRITER(hv) = riter; - HvEITER(hv) = eiter; - } + I32 items = (I32)HvPLACEHOLDERS(hv); + I32 i = HvMAX(hv); + + if (items == 0) + return; + + do { + /* Loop down the linked list heads */ + int first = 1; + HE **oentry = &(HvARRAY(hv))[i]; + HE *entry = *oentry; + + if (!entry) + continue; + + for (; entry; first=0, oentry = &HeNEXT(entry), entry = *oentry) { + if (HeVAL(entry) == &PL_sv_placeholder) { + *oentry = HeNEXT(entry); + if (first && !*oentry) + HvFILL(hv)--; /* This linked list is now empty. */ + if (HvEITER(hv)) + HvLAZYDEL_on(hv); + else + hv_free_ent(hv, entry); + + if (--items == 0) { + /* Finished. */ + HvTOTALKEYS(hv) -= HvPLACEHOLDERS(hv); + if (HvKEYS(hv) == 0) + HvHASKFLAGS_off(hv); + HvPLACEHOLDERS(hv) = 0; + return; + } + } + } + } while (--i >= 0); + /* You can't get here, hence assertion should always fail. */ + assert (items == 0); + assert (0); } STATIC void |