Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Using SV as key in hash

by liz (Monsignor)
on Jul 16, 2006 at 22:53 UTC ( #561609=perlquestion: print w/replies, xml ) Need Help??
liz has asked for the wisdom of the Perl Monks concerning the following question:

For my new Data::Reuse module (now on CPAN), I'm looking for a way to create a hash entry in which both the value as well as the key point to the same SV, or more general: set the hash key to a specific SV.

From what I've been able to learn from looking at a bunch of XS code, and [hs]v.[ch], the following code should do the trick:

#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" MODULE = Data::Reuse PACKAGE = Data::Reuse void key_as_sv( hv, key, val ) HV *hv SV *key SV *val PROTOTYPE: \%$$ CODE: SvREFCNT_inc(key); SvREFCNT_inc(val); STRLEN length = SvCUR(key); hv_store( hv, SvPV( key, length ), length , val, 0 ); HE *he = hv_fetch_ent( hv, key, 0, 0 ); HeSVKEY_set( he, key );

which would then be called thus:

my %hash; my $foo = 'foo'; Data::Reuse::key_as_sv( %hash, $foo, $foo ); print STDERR "found ".(keys %hash)." keys:\n"; print STDERR " $_: $hash{$_}\n" foreach keys %hash;

However, this produces the following output:

found 1 keys: foo:
or, in other words, the value of the key is gone.

I guess my question to any XS savvy Perl Monk is:

  • does it make sense to try to save memory this way?
  • if so, why doesn't the above work?

Thanks in advance for any insights.


Replies are listed 'Best First'.
Re: Using SV as key in hash
by Fletch (Chancellor) on Jul 17, 2006 at 01:41 UTC

    Gratuitous handwaving here since it's been ages since I mucked with XS, but . . .

    I want to say that the keys to an HV are always stringified and kept as char*, not as SV*s. A good starting place might be to look at what Tie::RefHash does and then implement something similar in your XS (possibly something like keeping your own internal mapping of char* to original SV*).

      I want to say that the keys to an HV are always stringified and kept as char*, not as SV*s.
      Well, that's just it. There is a provision in hv.c to actually have an SV as the key (rather than a char *). The HeSVKEY_set macro is supposed to be doing that.

      A good starting place might be to look at what Tie::RefHash does
      I'm afraid that Tie::RefHash doesn't have any XS component to obtain any inspiriation from ;-(


Re: Using SV as key in hash
by grinder (Bishop) on Jul 17, 2006 at 08:11 UTC

    I don't think you need to play with HeSVKEY_set directly. Assuming key is an SV, why not use hv_store_ent instead?

    CODE: SvREFCNT_inc(key); SvREFCNT_inc(val); hv_store_ent( hv, key, val, 0 );

    • another intruder with the mooring in the heart of the Perl

      Hmmm... Are you implying that by default key values are already shared? As this code in sv.c seems to imply:
      HV * Perl_newHV(pTHX) { register HV *hv; register XPVHV* xhv; hv = (HV*)NEWSV(502,0); sv_upgrade((SV *)hv, SVt_PVHV); xhv = (XPVHV*)SvANY(hv); SvPOK_off(hv); SvNOK_off(hv); #ifndef NODEFAULT_SHAREKEYS HvSHAREKEYS_on(hv); /* key-sharing on by default */ #endif

      But I assume then that what is being shared, are char * rather than SV's? And sharing between different hashes doesn't really solve my optimization "problem", as I only want to use one hash. It's just that in many cases the value is the same as the key, and that it would therefore make sense to have them share the same SV.


Re: Using SV as key in hash
by DrWhy (Chaplain) on Jul 17, 2006 at 19:17 UTC
    Not really a solution, but a suggestion for finding out what is really going on here. Try using Data::Dumper to dump your test hash. It could be that the key does not end up being what you expect it to be.


    "If God had meant for us to think for ourselves he would have given us brains. Oh, wait..."

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://561609]
Approved by Herkum
Front-paged by planetscape
[LanX]: oiskuu -I don't think so, but I already know the winner!
[oiskuu]: Why would you say you don't think so, but you already know the answer?
[choroba]: also, do cheating answers to most popular turing test questions exist on bot forums?
[Your Mother]: : Describe in single words. Only the good things that come to your mind. About Your mother.
[marto]: you make up these questions yourself, or do they write 'em down for you?
[choroba]: Can humans count?
[oiskuu]: She Showers at YMCA?
[Your Mother]: marto++
[oiskuu]: marto, that doesn't discriminate. A human would take that as a challenge.

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (10)
As of 2017-12-18 14:42 GMT
Find Nodes?
    Voting Booth?
    What programming language do you hate the most?

    Results (487 votes). Check out past polls.