Perl. shared hash threads in 2 files

Viewed 70

please help me resolve my problems with shared hash threads in 2 files

my first file "H.pl" contain defined hash (very huge with many levels):

#!usr/bin/perl
use strict;
use warnings;
our %h;
%h= (
        "hd",
                {
                    "0",    {"type",    "fix",  "ln",   "8",    "descr",    "P"},
                    "1",    {"type",    "hex",  "ln",   "2",    "descr",    "H"},
                },
        "hdr",
                {
                    "0",    {"type",    "fix",  "ln",   "8",    "descr",    "E"},
                },
    );

second file "V.pl" contain main code and threads for change hash:

#!usr/bin/perl

use strict;
use warnings;
use threads;
use threads::shared;
use Data::Dumper;
use lib '.';

require 'H.pl';

our %h;
threads->create(sub{  
                    
                    print "befor change in threads \n";
                    print Dumper \%h;  
                    
                    $h{"hd"}{"0"}{"value"}  = "hello"; 
                    $h{"hd"}{"0"}{"descr"}  = "R"; 
                    $h{"hdr"}{"0"}{"value"}  = "hello"; 
                    
                    print "after change in threads  \n";
                    print Dumper \%h;  
                    
                    }
                );

sleep 1;

print "without threads  \n";
print Dumper \%h;  

I tried use our %h:shared; in both files, but always get error Invalid value for shared scalar at H.pl How I can share my hash?

Thanks for help

1 Answers

Per the documentation:

Shared variables can only store scalars, refs of shared variables, or refs of shared data (discussed in next section):

If you want to share a hash that's not shallow, you need to share the inner references first.

You can use the shared_clone function for that. Adding the following line into V.pl below our %h makes the programs work:

%h = %{ shared_clone(\%h) };

Also, store the result of create to a variable $t and instead of sleep, run $t->join.

It's usually better to use a higher level module like Thread::Queue and only send the data you actually need between threads.

Related