user1895140
user1895140

Reputation: 109

Perl thread and shared variable

How can I shared a list of array in Perl ?

My code in sub thread:

@token_list = (@token_list, [$token, time() + 1200]);

My code in main sub:

my @array1 = [];
my @token_list : shared = ();
.
.
.
$thr = threads->new(\&connect, $c, $r);
.
.
.
foreach my $token_tab (@token_list)                                    
{               
   @array1 = @$token_tab;
   print "List content: $array1[0] $array1[1]\n";   
}

Because soft never enter into foreach

Upvotes: 1

Views: 622

Answers (1)

Sobrique
Sobrique

Reputation: 53478

First off - threads are officially discouraged in perl:

The "interpreter-based threads" provided by Perl are not the fast, lightweight system for multitasking that one might expect or hope for. Threads are implemented in a way that make them easy to misuse. Few people know how to use them correctly or will be able to provide help. The use of interpreter-based threads in perl is officially discouraged.

Anyway, that aside - you talk about sharing a nested data structure. The way you're doing that doesn't work.

The problem is - the way perl handles multidimensional data structures is via references.

So with your @token_list:

my @token_list = (@token_list, [$token, time() + 1200]);

You're actually doing:

my @token_list : shared;
my $anon_array = [ $token, time() + 1200 ];
@token_list = ( @token_list, $anon_array ); 

and because $anon_array isn't shared, it doesn't work 'properly'. In order to do this, you would need to share the 'sub' array separately. share doesn't work very well, but shared_clone does.

use strict;
use warnings;
use threads;
use threads::shared;
use Data::Dumper;

my @array_of_arrays : shared;

for ( 0 .. 5 ) {
    my $array_ref = [ 1, 2, 3, 4, 5 ];
    push( @array_of_arrays, shared_clone($array_ref) );
}

print Dumper \@array_of_arrays;

sub inc_all_elements {
    foreach my $outer (@array_of_arrays) {
        foreach my $inner (@$outer) {
            $inner++;
        }
        push( @$outer, 8 );
    }
}

for ( 1 .. 5 ) {
    threads->create( \&inc_all_elements );
}

foreach my $thr ( threads->list ) {
    $thr->join;
}

print Dumper \@array_of_arrays;

This makes the inner array reference 'shared' as well as the outer, which is what's missing from your code.

I think that means it would be as simple as:

@tokens = ( @tokens, shared_clone(  [$token, time() + 1200] ) );

To get your code working.

Upvotes: 1

Related Questions