Dr. Mu has asked for the wisdom of the Perl Monks concerning the following question:
That this subroutine is flawed should be obvious from the get-go: that dereferencing loop shouldn't have to be there. So I've blundered in the way I add new nodes. But the fact is that it works the way I want, when it's not being used on a shared hash.sub PutShare { print "Args: ", join(' | ', @_), "\n"; my $shr = shift; my $shrref = ref $shr; while ($shrref eq 'REF') { print " Dereferencing $shr "; $shr = $$shr; print "to get $shr\n"; $shrref = ref $shr } if (@_ > 1) { my $key = shift; print " Key = $key\n"; if ($shrref eq 'ARRAY') { print " Adding/using '$key' of existing array.\n"; PutShare(\($shr->[int($key)]), @_) } elsif ($shrref eq 'HASH') { print " Adding/using '$key' of existing hash.\n"; PutShare(\$shr->{$key}, @_) } elsif ($key =~/^\s[-+]?\d+/) { my $new = &share([]); print " Adding '$key' to new array.\n"; PutShare(\$new->[int($key)], @_); $$shr = $new } else { my $new = &share({}); print " Adding '$key' to new hash: $new\n"; PutShare(\$new->{$key}, @_); $$shr = $new } } else { my $val = shift; print " Value = '$val'\n"; my $valref = ref $val; if ($valref eq 'ARRAY') { my $new = &share([]); @$new = @$val; $$shr = $new } elsif ($valref eq 'HASH') { my $new = &share({}); %$new = %$val; $$shr = $new } else { $$shr = $val; } print "\n"; } }
Here's the sample code I used to test it:
If I comment out the use threads (turning share into a nop), the output I get is this:use strict; use warnings; use threads; use threads::shared; use Data::Dump qw/dump/; my %User; PutShare(\%User, qw/deep fish tuna/); PutShare(\%User, qw/deep deeper fish halibut/); print "The resulting leaves are: '$User{deep}{fish}' and '$User{deep}{ +deeper}{fish}'\n"; print "\nDump: ", dump(\%User);
But with the use threads active, I get essentially the same output except for the dump:Args: HASH(0x18241f8) | deep | fish | tuna Key = deep Adding/using 'deep' of existing hash. Args: SCALAR(0x224fa4) | fish | tuna Key = fish Adding 'fish' to new hash: HASH(0x1890b98) Args: SCALAR(0x1890ba4) | tuna Value = 'tuna' Args: HASH(0x18241f8) | deep | deeper | fish | halibut Key = deep Adding/using 'deep' of existing hash. Args: REF(0x224fa4) | deeper | fish | halibut Dereferencing REF(0x224fa4) to get HASH(0x1890b98) Key = deeper Adding/using 'deeper' of existing hash. Args: SCALAR(0x1890bb0) | fish | halibut Key = fish Adding 'fish' to new hash: HASH(0x18af2c0) Args: SCALAR(0x18af2cc) | halibut Value = 'halibut' The resulting leaves are: 'tuna' and 'halibut' Dump: { deep => { deeper => { fish => "halibut" }, fish => "tuna" } }
And dump complains about the lvalue.Dump: { deep => { deeper => { fish => '#LVALUE#' }, fish => "tuna" } }
Anyway, I'm not there yet. Perhaps the Monks can see some detail I've overlooked.
As an aside, I'm quite annoyed that this is even necessary. threads::shared should have provided autovivification built-in. Why make every user try to do it on his/her own?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: "Auto" vivifying shared data structures
by jdhedden (Deacon) on Nov 17, 2005 at 20:53 UTC | |
by Dr. Mu (Hermit) on Nov 17, 2005 at 21:17 UTC | |
|
Re: "Auto" vivifying shared data structures
by johnnywang (Priest) on Nov 17, 2005 at 20:53 UTC | |
by Dr. Mu (Hermit) on Nov 17, 2005 at 21:24 UTC | |
|
Re: "Auto" vivifying shared data structures
by dave_the_m (Monsignor) on Nov 17, 2005 at 22:01 UTC | |
by BrowserUk (Patriarch) on Nov 17, 2005 at 22:28 UTC | |
by dave_the_m (Monsignor) on Nov 17, 2005 at 22:58 UTC | |
by Dr. Mu (Hermit) on Nov 17, 2005 at 22:28 UTC |