I've had success sharing multi-dimensional hash references by constructing
them like:
my $hash = &share({});
$hash->{$tid} = &share({});
$hash->{$tid}->{foo} = 'bar';
and so on. Then your parent loop becomes
> parent:
> foreach $row ( keys %$hash) {
> if ($hash->{$row}->{state} eq 'idle') {
> $hash->{$row}->{state} = 'go';
> }
> }
which should make $hash->{$row}->{state} readable by your threads. I'm
using a similar method of communication between threads and it's working
pretty well. Actually, I should mention that I'm running Red Hat 9, not
ActivePerl/Windows, so I suppose it's possible we're seeing different
behavior. Also, if your hash values are blessed references, they will lose
their blessing as soon as you assign them to the shared hash.
Hope this is helpful. I can be more specific about what's working for me if
necessary.
Jack Steadman
> -----Original Message-----
> From: Adam B.Meltzer (KF6PDH) [mailto:[EMAIL PROTECTED]
> Behalf Of [EMAIL PROTECTED]
> Sent: Thursday, June 12, 2003 6:49 PM
> To: [EMAIL PROTECTED]
> Subject: ithreads and multi-dimensional hashes: possible?
>
>
> I've been beating my head against the wall trying to get this to
> work with no
> success, so I figured I'd turn to the experts.
>
> I'm trying to manage a pool of threads, and I figured the best way to
> instruct the threads to do work and figure out when they are finished is
> through a hash set that each thread looks at.
>
> Excuse my psuedo-code, but something sort of like this is what
> I'm trying to
> accomplish:
>
> shared: $hash{thread1}{state}
>
> parent:
> foreach $row ( keys %hash) {
> if ($hash{$row}{state} eq 'idle') {
> $hash{thread1}{state} = 'go';
> }
> }
>
> thread:
> while(1) {
> if ($hash{mytid}{state} eq 'go') {
> do_work;
> };
> }
>
> Before I proceed, if anyone has *any* better ideas on how to do
> this, by all
> means let me know. I'm open to suggestions. :) Also, I'd like to
> note that I
> have had successes in sharing scalars, but this is my first
> forray into sharing
> hashes. This program launches hundreds of threads if I set it up fire-and-
> forget style, so I need to use a pool of threads or else it uses
> hundreds of
> megs of memory in just minutes. Fork()ing doesn't work properly since I'm
> unable to share state information (without using serialization --
> I want to
> avoid such hackery if possible).
>
> So, now on to the problem. I have written a test program to
> demonstrate the
> problem that I'm having. Here is the test program:
>
> use threads;
> use threads::shared;
>
> my %test : shared = ();
>
> $test{'a'} = "a = a";
> $test{'a'}{'b'} = "a+b = c";
>
> print "[parent] test->a = $test{'a'}\n";
> print "[parent] test->a->b = $test{'a'}{'b'}\n";
>
> my $thread = async {
> $test{'a'}{'b'} = "a+b = t";
> print "[thread] test->a->b = $test{'a'}{'b'}\n";
> return;
> };
>
> # Give the thread a moment to work.
> sleep 1;
> print "[parent] test->a->b = $test{'a'}{'b'}\n";
>
> Here is the output:
> D:\scripts>perl test
> [parent] test->a = a = a
> [parent] test->a->b = a+b = c
> [thread] test->a->b = a+b = t
> [parent] test->a->b = a+b = c
>
> I give the parent a moment to sleep to ensure that the thread
> does its work
> but as you can see from the output, when the thread sets $test{a}{b} it
> obviously doesn't set it for the parent.
>
> Now, if I turn on strict the program fails altogether since I'm
> trying to set
> a text string as a hash ref which doesn't work in the strict world.
>
> Next if I modify the code like this:
> #use strict;
> use threads;
> use threads::shared;
>
> my %test : shared = ();
>
> $test{'a'}{'b'} = c;
>
> When I run the program here's what happens:
>
> D:\scripts>perl test
> Invalid value for shared scalar at test line 7.
>
> Very frustrating! I'm using ActivePerl 806 on a Windows 2000
> Server system.
> Because of this, I can't use forks.pm.
>
> Is there a solution to this, or is there a better way to do the
> pooling and
> process handling that I want?
>
> Any advice would be most appreciated.
>
>
>