Adler has asked for the wisdom of the Perl Monks concerning the following question:

Hi to all, i am new to perl and need your help. I am trying to share an array of hashes between my main program and a thread, but i get an error. I wrote an example that illustrate my program:
#!/usr/bin/perl -w use warnings; use strict; use threads; use threads::shared; my @Array : shared = (); my $thr = threads->create( \&handle_array , \@Array ); while( 1 ) { do_something(\@Array); printf "Main: Number of files: ". scalar(@Array) . "\n"; sleep 5; } sub do_something { my ( $Array_ref ) = shift; push( @{$Array_ref} , {file => 'test1.zip', price => '10.00', d +esc => 'the 1st test'} ); sleep 10; } sub handle_array { my ( $Array_ref ) = shift; while (1) { printf STDOUT "Thread: Number of elements before: %d\n", scala +r(@{$Array_ref}); push( @{$Array_ref} , {file => 'test1.zip', price => '10.00' +, desc => 'the 1st test'} ); printf STDOUT "Thread: Number of elements after: %d\n", scalar +(@$Array_ref); sleep 10; } }
after running this code, i get

Invalid value for shared scalar at foo.pl line 22.

since i am newbie, do i need to use "\" to my array? it make sence, but if it is from the first place shared, then... Regards

Replies are listed 'Best First'.
Re: share array of hashes between main program and thread
by BrowserUk (Patriarch) on Nov 05, 2009 at 20:55 UTC

    Try it this way:

    #!/usr/bin/perl -w use warnings; use strict; use threads; use threads::shared; my @Array : shared = (); my $thr = threads->create( \&handle_array , \@Array ); while( 1 ) { do_something(\@Array); printf "Main: Number of files: ". scalar(@Array) . "\n"; sleep 5; } sub do_something { my ( $Array_ref ) = shift; my %hash : shared = ( file => 'test1.zip', price => '10.00', desc => 'the 1st test' ); push @{ $Array_ref } , \%hash; } sub handle_array { my ( $Array_ref ) = shift; while (1) { printf STDOUT "Thread: Number of elements before: %d\n", scalar @{ $Array_ref }; my %hash :shared = ( file => 'test1.zip', price => '10.00', desc => 'the 1st test' ); push( @{$Array_ref} , \%hash ); printf STDOUT "Thread: Number of elements after: %d\n", scalar @{ $Array_ref }; sleep 10; } }

    The main point is that any structures (references) you push into a shared array, have also to be shared themselves.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thank, that solved the problem. now i would like ask in addition, how could i add an additional single hash to a line i ($i) of my array of hashes after the line:
      push( @{$Array_ref} , \%hash );
      for example, i create my array of hashes (in a thread) and then send the array of hashes reference to an additional function. Then i tried (in the new function)
      @Array = @$Array_ref; $Array[$i]{'foo'}->$boo
      once i tired to call the new hash (in line i)  $Array[$i]{'foo'} i got an error massage of uninitialized value. I can think of the reason why it is like that and that is since my new hash i am trying to add is not "shared"... but i dont know how to add a single shared hash to $Array$i. thanks
        how could i add an additional single hash to a line i ($i) of my array of hashes

        Do you mean: how can I add an extra key-value pair to one of the hashes in my AoH?

        Assuming you do, like this:

        $Array[ $i ]{ newKey } = 'newValue'.

        Once the reference is shared (or is a reference to a shared hash--same thing), adding pairs is just the same as normal. Because scalars, (keys and values) are shared by value. Only references are shared by reference.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: share array of hashes between main program and thread
by bichonfrise74 (Vicar) on Nov 05, 2009 at 20:55 UTC
    I think you are just missing to return the values after you push your data, this is why you are not getting any data and causing you to get an error. Please see below.
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my @array; my $new_array = do_something( @array ); print Dumper \$new_array; sub do_something { my ( $Array_ref ) = shift; push( @{ $Array_ref } , { file => 'test1.zip', price => '10.00', desc => 'the 1st test' } ); return $Array_ref; }