Promise-Me

 view release on metacpan or  search on metacpan

lib/Promise/Me.pm  view on Meta::CPAN


Boolean. Default to true. If true, the shared space used by the parent and child processes will be destroy automatically. Disable this if you want to debug or take a sneak peek into the data. The shared space will be either shared memory of cache fil...

=head2 tmpdir

The optional path to the temporary directory to use when you want to use file cache as a medium for shared data.

=head2 use_async

This is a boolean value which is set automatically when a promise is instantiated from L</async>.

It enables subroutine arguments to be passed to the code being run asynchronously.

=head1 PRIVATE METHODS

=head2 _browse

Used for debugging purpose only, this will print out the L<PPI> structure of the code filtered and parsed.

=head2 _parse

After the code has been collected, this method will quickly parse it and make changes to enable L</async>

=head2 _reject_resolve

This is a common code called by either L</resolve> or L</reject>

=head2 _set_exit_values

This is called upon the exit of the asynchronous process to set some general value about how the process exited.

See L</exit_bit>, L</exit_signal> and L</exit_status>

=head2 _set_shared_space

This is called in L</exec> to share data including result between main parent process and asynchronous process.

=head1 SHARED VARIABLES

It is important to be able to share variables between processes in a seamless way.

When the asynchronous process is executed, the main process first fork and from this point on all data is being duplicated in an impermeable way so that if a variable is modified, it would have no effect on its alter ego in the other process; thus th...

You can enable shared variables in two ways:

=over 4

=item 1. declaring the variable as shared

    my $name : shared;
    # Initiate a value
    my $location : shared = 'Tokyo';
    # you can also use 'pshared'
    my $favorite_programming_language : pshared = 'perl';
    # You can share array, hash and scalar
    my %preferences : shared;
    my @names : shared;

=item 2. calling L</share>

    my( $name, %prefs, @middle_names );
    share( $name, %prefs, @middle_names );

=back

Once shared, you can use those variables normally and their values will be shared between the parent process and the asynchronous process.

For example:

    my( $name, @first_names, %preferences );
    share( $name, @first_names, %preferences );
    $name = 'Momo Taro';

    Promise::Me->new(sub
    {
        $preferences{name} = $name = 'Mr. ' . $name;
        print( "Hello $name\n" );
        $preferences{location} = 'Okayama';
        $preferences{lang} = 'ja_JP';
        $preferences{locale} = '桃太郎';
        my $rv = $tbl->insert( \%$preferences )->exec || die( My::Exception->new( $tbl->error ) );
        $rv;
    })->then(sub
    {
        my $mail = My::Mailer->new(
            to => $preferences{email},
            name => $preferences{name},
            body => $welcome_ja_file,
        );
        $mail->send || die( $mail->error );
    })->catch(sub
    {
        my $exception = shift( @_ );
        $logger->write( $exception );
    })->finally(sub
    {
        $dbh->disconnect;
    });

If you want to mix this feature and the usage of threads' C<shared> feature, use the keyword C<pshared> instead of C<shared>, such as:

    my $name : pshared;

Otherwise the two keywords would conflict.

=head1 SHARED MEMORY

This module uses shared memory using L<Module::Generic::SharedMemXS>, or shared cache file using L<Module::Generic::File::Cache> if shared memory is not supported, or if the value of the global package variable C<$SHARE_MEDIUM> is set to C<file> inst...

The value of C<$SHARE_MEDIUM> is automatically initialised to C<memory> if the system, on which this module runs, supports L<IPC::SysV>, or C<mmap>, or else to C<file>

Shared memory is used for:

=over 4

=item 1. shared variables

=item 2. storing results returned by asynchronous processes

=back

You can control how much shared memory is allocated for each by:

lib/Promise/Me.pm  view on Meta::CPAN


    use Time::HiRes;
    my $result : shared = '';
    my $p1 = Promise::Me->new(sub
    {
        sleep(1);
        $result .= "Peter ";
    })->then(sub
    {
        print( "Promise 1: result is now: '$result'\n" );
    });

    my $p2 = Promise::Me->new(sub
    {
        sleep(0.5);
        $result .= "John ";
    })->then(sub
    {
        print( "Promise 2: result is now: '$result'\n" );
    });
    await( $p1, $p2 );
    print( "Result is: '$result'\n" );

This will yield:

    Promise 2: result is now: 'John '
    Promise 1: result is now: 'John Peter '
    Result is: 'John Peter '

=head1 CLASS VARIABLE

=head2 $RESULT_MEMORY_SIZE

This is the size in bytes of the shared memory block used for sharing result between sub process and main process, such as when you call:

    my $res = $prom->result;

It defaults to 512Kb

=head2 $SERIALISER

A string representing the serialiser to use by default. A serialiser is used to serialiser data to share them between processes. This defaults to C<storable>

Currently supported serialisers are: L<CBOR::XS>, L<Sereal> and L<Storable|Storable::Improved>

You can set accordingly the value for C<$SERIALISER> to: C<cbor>, C<sereal> or C<storable>

You can override this global value when you instantiate a new L<Promise::Me> object with the C<serialiser> option. See L</new>

Note that the serialiser used to serialise shared variable, is set only via this class variable C<$SERIALISER>

=head2 $SHARE_MEDIUM

The value of C<$SHARE_MEDIUM> is automatically initialised to C<memory> if the system, on which this module runs, supports L<IPC::SysV>, or C<mmap>, or else to C<file>

=head2 $SHARED_MEMORY_SIZE

This is the size in bytes of the shared memory block used for sharing variables between the main process and the sub processes. This is used when you share variables, such as:

    my $name : shared;
    my( $name, %prefs, @middle_names );
    share( $name, %prefs, @middle_names );

See L</"SHARED VARIABLES">

=head2 $USE_THREADS_SHARED

    my $data : shared = '';
    # Do some asynchronous activities with Promise::Me

or

    my $data : pshared = ''; # does the same thing, but avoid conflict with threads

By default, C<Promise::Me> will recognise the variable attribute C<shared>, and handle it. However, when using L<threads>, this C<shared> pragma would also be used and recognised by L<threads> leading to a conflict. Setting C<$USE_THREADS_SHARED> to ...

Also, instead of using C<shared>, you can use C<pshared>

You can also set the value of C<$USE_THREADS_SHARED> upon import by using C<no_shared>

    use Promise::Me 'no_shared'; # effectively sets $USE_THREADS_SHARED to true

However, if you did:

    use Promise::Me;
    $Promise::Me::USE_THREADS_SHARED = 1;

This would not work, because it would be too late. C<$USE_THREADS_SHARED> is used when the module is being loaded in the caller's namespace, so setting the variable after would be too late.

=head1 SHARED VARIABLES

C<Promise::Me> supports two attributes for shared variables:

=over 4

=item C<:shared>

Shares variables across processes or threads. By default, or if C<$USE_THREADS_SHARED> is false, C<:shared> uses C<Promise::Me::Share> with shared memory (via L<Module::Generic::SharedMemXS>) and customisable serialisation (e.g., L<CBOR>, L<Sereal>)....

=item C<:pshared>

Always uses C<Promise::Me::Share> for sharing, regardless of C<threads> usage or the C<no_shared> option. This ensures consistent inter-process sharing with C<Promise::Me>’s mechanism.

=back

To avoid conflicts with dependencies that load C<threads> (e.g., under C<mod_perl>), use C<:pshared> or avoid C<no_shared>. If you explicitly use C<threads>, call C<Promise::Me> with C<no_shared> to prefer C<threads::shared> for C<:shared>.

Example:

    use Promise::Me;
    my $result : shared = '';  # Uses Promise::Me::Share
    my $promise = Promise::Me->new(sub
    {
        $result = "data from child";
    });
    await($promise);
    print $result;  # Outputs: data from child

    use threads;
    use threads::shared;
    use Promise::Me qw( no_shared );
    my $result : shared = '';  # Uses threads::shared



( run in 1.375 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )