It would be impractical and very difficult to build a shared multilevel hash on the fly, but you don't really need to. Do your expensive processing in your threads then build your multilevel hash in the main thread. Pass the parameters through a shared buffer. Here's my earlier script updated to use queues and a buffer. Note: a bunch of code stolen from BrowserUks example above.
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use threads ( stack_size => 4096 );
use threads::shared;
use Thread::Queue;
my %count;
my @buffer : shared;
my $maxthreads = 5;
my $queue = Thread::Queue->new;
my @threads = map threads->create( \&inc, $queue, \@buffer ), 1 .. $ma
+xthreads;
# there are way more lines than this but anyway...
for my $i ( 1 .. 500 ) {
# this just represents that I've found a pair and want to run the
+sub
if ( $i % 50 == 0 ) {
# push the pair in the queue
$queue->enqueue("$i:2");
}
empty_buffer( \@buffer ) if @buffer;
}
$queue->enqueue( (undef) x $maxthreads );
$_->join for @threads;
empty_buffer( \@buffer ) while @buffer;
print Dumper \%count;
sub inc {
my ( $queue, $arrayref ) = @_;
my $tid = threads->tid;
while ( my $param = $queue->dequeue ) {
# long subroutine using passed params
# pausing for effect!
# this simulates that the sub takes a while to run
sleep( 2 + rand 5 );
# let you know something is happening
print "Thread# $tid | Parameter: $param\n";
my ( $p1, $p2 ) = split /:/, $param;
# add it to the buffer
lock $arrayref;
push @{$arrayref}, "$p1:$p2:" . $p1 * $p2;
}
}
sub empty_buffer {
my $buffref = shift;
my ( $p1, $p2, $result ) = split /:/, shift @{$buffref};
$count{$p1}{$p2} = $result;
}
|