use strict; use warnings; package Foo { use MCE::Shared ; sub new { my $class = shift ; my $this = { } ; tie my %data, 'MCE::Shared', _var => 1 ; $this->{ _SHARED_DATA } = \%data ; $this->{ _MUTEX } = MCE::Mutex->new ; bless $this, $class ; } sub task { # Long operation task Foo ~ 2 seconds my $this = shift ; print "Starting task Foo for $_[0]\n" ; sleep 2 ; $this->{ _MUTEX }->enter( sub { ++$this->{ _SHARED_DATA }{ _var } ; }) ; print "Finished task Foo for $_[0]\n" ; } sub export { my $this = shift ; my %clone = %{ $this } ; delete $clone{ _MUTEX } ; return \%clone ; } } ; package Bar { use MCE::Shared ; use Scalar::Util 'blessed' ; sub new { my $class = shift ; # This is not very realistic code. # here it is just used as an # example to create an object that # contains a nested object my $this = { nestedFoo => $_[0] } ; tie my %data, 'MCE::Shared', _var => 1 ; $this->{ _SHARED_DATA } = \%data ; $this->{ _MUTEX } = MCE::Mutex->new ; bless $this, $class ; } sub task { my $this = shift ; if ( @_ == 2 ) { $this->{ $_[0] }->task( $_[1] ) ; return ; } # Long operation task Bar ~ 6 seconds print "Starting task Bar for $_[0]\n" ; sleep 6 ; $this->{ _MUTEX }->enter( sub { ++$this->{ _SHARED_DATA }{ _var } ; }) ; print "Finished task Bar for $_[0]\n" ; } sub export { my $this = shift ; my %clone = %{ $this } ; delete $clone{ _MUTEX } ; for ( keys %clone ) { next unless blessed( $clone{ $_ } ) ; next unless $clone{ $_ }->can('export') ; $clone{ $_ } = $clone{ $_ }->export ; } return \%clone ; } } ; package main ; use MCE::Hobo ; use Data::Dumper ; my $foo = Foo->new ; my $bar = Bar->new( $foo ) ; print Dumper( $bar->export ), "\n" ; mce_async { $bar->task('Bar') } ; mce_async { $bar->task('nestedFoo', 'Foo') } ; MCE::Hobo->waitall ; print "\n", Dumper( $bar->export ), "\n" ;