in reply to Declaring/Assigning thread shared vars
gives the error: 'Invalid value for shared scalar '
lock(%cfg::thash); $v1="A"; $v2="1"; $cfg::thash{$v1}{$v2} ="b";
The problem is that this line of code:
$cfg::thash{$v1}{$v2} ="b";
is equivalent to
## Make the value of key 'A' an anonymous hash. $cfg::thash{A} = {}; ## add a key '1' to that anonymous hash with the value "b"; $cfg::thash{A}{1} = "b";
The thing with shared hashes (and shared arrays), is that everything you put into them also has to be shared.
What's more, you cannot share an array or hash that already has data in it. Or rather you can, but it will silently empty it in the process. This is (apparently) a deliberate design decision---and a bad one in my opinion as it makes using shared hashes and arrays almost impossible.
The basis of the decision (as it was explained to me) is that if adding elements to a shared hash automatically shared the things you put in it, then it would have to be a recursive process scanning through anything in the things you added sharing them. Ie. If you add a reference to an existing deeply nested datastructure (eg. a HoAoHoA...), then adding that reference to a shared hash, would require the entire nested structure to be traversed and all it's sub elements shared.
This was deemed likely to take too long. It was easier to issue an uninformative error message and force the user to do the traverse. Except of course, this kind of complex processing is difficult to get right, almost impossible in user space, and exactly the kind of thing that should be done by a piece of write-it-once, get-it-right-once, tight (XS) library code.
This is why I tend to avoid sharing compex datastructures in my threaded code. It renders autovivication impossible to use, which make using them messy and awkward.
Anyway, you can do what you are trying to do by sharing the intermediate elements individually and building the stricture up. However, due to the use (and limitations of) perl prototypes on the threads::shared::share() function, you cannot use it on anonymous hashes or arrays directly. Instead, you have to assign a ref to them to a temporary scalar and then apply share() to that.
This will do what you asked about:
use strict; use threads; use threads::shared; my %thash : shared; ## Share the base hash my $temp = {}; ## Get a reference to an anon. hash in a temp var share( $temp ); ## share() the temp var $thash{A} = $temp; ## assign it into the structure $thash{A}{1} = 'b'; ## At this point you have what you asked for.
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Declaring/Assigning thread shared vars
by diotalevi (Canon) on Nov 18, 2004 at 01:47 UTC | |
by BrowserUk (Patriarch) on Nov 18, 2004 at 03:07 UTC |