Greetings Veltro,

Yet another interesting use case :)

Q & A

In case objects are shared that do not have STORE and FETCH methods, and they have nested methods and objects, does this mean that the methods cannot be reached and the objects don't get to be shared?

Is there a way to 'get' the nestedFoo in shared context?

Is there a way to execute task for Foo without export?

For shared objects, think of them as having an entry point into the shared-manager process. Important for shared-objects, in the case of MCE::Shared, is to pass arguments instead of dereferencing. Please note that calling a method on a shared-object is executed by the shared-manager where the data resides. For this use case, embed the shared-data object inside the class. That will allow workers to run in parallel and update shared-data accordingly.

Demo 1: via Perl-like behavior

Shown with mutex in the event multiple workers update the same key. Like in the prior post, the reason is because ++ involves two trips to the shared-manager process { FETCH and STORE }. I added an export routine to filter out the mutex handle.

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" ;

Demo 2: using the OO interface

This eliminates the mutex at the application level. Here, the export routine calls export on the shared-data object.

use strict; use warnings; package Foo { use MCE::Shared ; sub new { my $class = shift ; my $this = { } ; $this->{ _SHARED_DATA } = MCE::Shared->hash( _var => 1 ) ; bless $this, $class ; } sub task { # Long operation task Foo ~ 2 seconds my $this = shift ; print "Starting task Foo for $_[0]\n" ; sleep 2 ; $this->{ _SHARED_DATA }->incr('_var') ; print "Finished task Foo for $_[0]\n" ; } sub export { my $this = shift ; my %clone = %{ $this } ; $clone{ _SHARED_DATA } = $this->{ _SHARED_DATA }->export( { unbless => 1 } ) ; 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] } ; $this->{ _SHARED_DATA } = MCE::Shared->hash( _var => 1 ) ; 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->{ _SHARED_DATA }->incr('_var') ; print "Finished task Bar for $_[0]\n" ; } sub export { my $this = shift ; my %clone = %{ $this } ; for ( keys %clone ) { next unless blessed( $clone{ $_ } ) ; next unless $clone{ $_ }->can('export') ; $clone{ $_ } = $clone{ $_ }->export( { unbless => 1 } ) ; } 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" ;

Output

$VAR1 = { '_SHARED_DATA' => { '_var' => 1 }, 'nestedFoo' => { '_SHARED_DATA' => { '_var' => 1 } } }; Starting task Bar for Bar Starting task Foo for Foo Finished task Foo for Foo Finished task Bar for Bar $VAR1 = { '_SHARED_DATA' => { '_var' => 2 }, 'nestedFoo' => { '_SHARED_DATA' => { '_var' => 2 } } };

Regards, Mario


In reply to Re^3: Hobo with a bit of recursion by marioroy
in thread Hobo with a bit of recursion by Veltro

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.