{ package shareDeep; ## threads::shareDeep is the intended name for release... use strict; use warnings; use threads; use threads::shared qw[ bless ]; use Carp qw[cluck carp]; use Scalar::Util qw[ readonly reftype blessed ]; require Exporter; our @ISA = 'Exporter'; our @EXPORT = qw[ shareDeep ]; our $TRACE = 0; *_trace = $TRACE ? sub{ my $fmt = shift; warn( sprintf "%3d %s(%d): %s\n", threads->self->tid || 0, __FILE__, __LINE__, $fmt, @_ ); } : sub(){ 0 }; sub _invalid { warn( "Can't share '$_[ 0 ]'; substituting as placeholder\n", ); return "$_[ 0 ]"; } sub getType { blessed( $_[ 0 ] ) ? reftype( $_[ 0 ] ) : ref( $_[ 0 ] ); } my %do; %do = ( '' => sub { _trace( "VALUE: @_ : " . getType( $_[ 0 ] ) ); $_[ 0 ] }, SCALAR => sub { _trace( "SCALAR: @_ : " . getType( $_[ 0 ] ) ); my $scalar :shared = ${ $_[ 0 ] }; \$scalar }, HASH => sub { _trace( "HASH: @_ : " . getType( $_[ 0 ] ) ); my $in = shift; my %hash :shared = map { $_ => $do{ getType( $in->{ $_ } ) }->( $in->{ $_ } ) } keys %{ $in }; \%hash; }, ARRAY => sub { _trace( "ARRAY: @_ : " . getType( $_[ 0 ] ) ); my @array :shared = map{ $do{ getType( $_ ) }->( $_ ) } @{ $_[ 0 ] }; \@array; }, REF => sub { _trace( "REF: @_ : " . getType( $_[ 0 ] ) ); my $ref :shared = $do{ getType( ${ $_[ 0 ] } ) }->( ${ $_[ 0 ] } ); \$ref }, GLOB => \&_invalid, LVALUE => \&_invalid, CODE => \&_invalid, Regexp => \&_invalid, ); readonly( \%do ); sub shareDeep { my( $in ) = shift; return my $out :shared = $do{ getType( $in) }->( $in ); } } return 1 if caller; package main; use threads; use threads::shared qw[ bless ]; use Data::Dump qw[ pp ]; $Data::Dump::MAX_WIDTH = 500; shareDeep->import; sub test{ print "test sub @_" }; my %test = 1 .. 10; my $rSharedHash = shareDeep( \%test ); pp $rSharedHash; my @test = 1 .. 10; my $rSharedArray = shareDeep( \@test ); pp $rSharedArray; my $test = 'test'; my $rSharedScalar = shareDeep( \$test ); pp $rSharedScalar; my $rSharedRef = shareDeep( \\$test ); pp $rSharedRef; $rSharedRef = shareDeep( \\\\\\\\\\$test ); pp $rSharedRef; my $lvalue = \substr( 'fred', 1, 2 ); my $sharedLvalue :shared = shareDeep( $lvalue ); pp $sharedLvalue; my $glob = do{ local *GLOB; \*GLOB }; my $sharedGlob :shared = shareDeep( $glob ); pp $sharedGlob; my %hash = ( array => \@test, hash => \%test, ); my $nested :shared = shareDeep( \%hash ); pp $nested; my $blessed :shared = shareDeep( threads::shared::bless [], 'fred' ); print pp $blessed;