Async:...gePoint(3pm)
πΈ Async::MergePoint π
okay so bestie, picture this: Async::MergePoint β it resynchronises diverged control flow β¨. That's the whole vibe. It's a Perl module (obvs, we're in the perl v5.36.0 docs, dated 2022-10-13, iykyk) and it's about to become your new hyperfixation.
β¨ SYNOPSIS β¨
no thoughts, just tea. literally. watch:
use Async::MergePoint;
my $merge = Async::MergePoint->new(
needs => [ "leaves", "water" ],
);
my $water;
Kettle->boil(
on_boiled => sub { $water = shift; $merge->done( "water" ); }
);
my $tea_leaves;
Cupboard->get_tea_leaves(
on_fetched => sub { $tea_leaves = shift; $merge->done( "leaves" ); }
);
$merge->close(
on_finished => sub {
# Make tea using $water and $tea_leaves
}
);
the kettle and the cupboard are doing their thing at the same time, and the merge point is like "okay I'll wait for both of you, no rush, main character energy" π«Ά
π DESCRIPTION π
okay so here's the situation. in program logic you constantly have multiple different steps that need to happen, and they're all independent of each other β but you need the total result of all of them before you can move on to the next step. in synchronous code, the normal move is just... do them one after another. sequential. kinda slow ngl.
an asynchronous or event-based program could do that too. BUT, if each step involves some IO idle time, you can usually get way better overall performance by running the steps in parallel π₯. that's where a Async::MergePoint object comes in β you use it to wait for all the steps to complete, and then pass the combined result of each step on to the next stage. slay.
so a merge point keeps a set of outstanding operations it's waiting on. these are arbitrary string values that you hand over when you construct the object. every time the done() method gets called, whichever item was named gets marked as complete. and the second all the required items are marked like that β boom β the on_finished continuation gets invoked. β¨
now, for use cases where your code might be split across several different lexical scopes, it might not be convenient or even possible to share a lexical variable to pass on the result of some asynchronous operation. ngl that's a mood. so in those cases, when you mark an item as complete you can also hand over a value containing the results of that step. the on_finished callback gets passed a hash (in list form, not by reference, ok bestie, don't come for me) of all the collected item values. π
fun lore drop: this module was originally part of the IO::Async distribution, but it got removed β under the inspiration of Pedro Melo's Async::Hooks distribution β because it doesn't itself contain anything IO-specific. it's just vibing on its own now. π
π§ CONSTRUCTOR π§
$merge = Async::MergePoint->new( %params )
this function returns a new instance of a Async::MergePoint object. (yes, "a Async::MergePoint", we don't make the rules.) the %params hash takes the following keys:
needs => ARRAYβ Optional. an array containing unique item names to wait on. the order of this array is not significant, so don't stress about it. β¨on_finished => CODEβ Optional. aCODEreference to the continuation for when the merge point becomes ready. if you provide it here, it'll be passed straight to theclosemethod. convenient!
π METHODS π
$merge->close( %params )
lets you set an on_finished continuation if you didn't already provide one to the constructor. no biggie, you can always fix it later, we support that.
on_finished => CODEβ aCODEreference to the continuation for when the merge point becomes ready.
so the on_finished continuation gets called when every key in the needs list has been notified via the done() method. it gets called like this:
$on_finished->( %items )
where the %items hash contains the item names that were waited on, plus the values that were passed to the done() method for each one. and again, note that this is passed as a list, not as a HASH reference. π don't forget it.
now β while you can use this feature to pass data from the component parts back up into the continuation, it may honestly be more direct to just use normal lexical variables instead. either way works. the actual perk of this method is that it lets you put the continuation after the blocks of code that execute the component parts, so it reads downwards, which may make it more readable. it's giving narrative flow. π
$merge->needs( @keys )
when you call this on an open MergePoint (i.e. one that does not yet have an on_finished continuation), it adds extra key names to the set of outstanding names. the order of this list is not significant.
β οΈ this method throws an exception if the MergePoint is already closed. so, like, close it and then try to add more? absolutely not. the audacity.
$merge->done( $item, $value )
this method tells the merge point that $item is now ready, and passes it a $value to store β that value will be passed into the on_finished continuation later. π«Ά
if this call gives the final remaining item that was being waited for, then the on_finished continuation is called within it, and the method will not return until that continuation has completed. so yes, it blocks. it said "I'm finishing this, and you're going to sit here with me." periodt. π
π EXAMPLES π
Asynchronous Plugins
consider a program using Module::Pluggable to provide a plugin architecture that responds to events, where sometimes the response to an event may require asynchronous work. a MergePoint object can be used to coordinate the responses from the plugins to this event. coordinated. iconique.
my $merge = Async::MergePoint->new();
foreach my $plugin ( $self->plugins ) {
$plugin->handle_event( "event", $merge, @args );
}
$merge->close( on_finished => sub {
my %results = @_;
print "All plugins have recognised $event\n";
} );
each plugin that wants to handle the event can use its own package name as its unique key name for the MergePoint, for example. a plugin handling the event synchronously could do something like:
sub handle_event
{
my ( $event, $merge, @args ) = @_;
....
$merge->needs( __PACKAGE__ );
$merge->done( __PACKAGE__ => $result );
}
whereas, to handle the event asynchronously, the plugin can instead do:
sub handle_event
{
my ( $event, $merge, @args ) = @_;
....
$merge->needs( __PACKAGE__ );
sometime_later( sub {
$merge->done( __PACKAGE__ => $result );
} );
}
same energy, different timeline. the merge point does not care which one you pick, it only cares that you eventually call done(). π¦
πΈ AUTHOR πΈ
Paul Evans <leonerd@leonerd.org.uk> β thank you for your service king π
and that's the whole page bestie!! this was Async:...gePoint(3pm) from the User Contributed Perl Documentation, shipped with perl v5.36.0, dated 2022-10-13. go forth and merge your control flow, you gorgeous parallel-processing legend πβ¨π
π¦ where this page comes from
- ubuntu noble: libasync-mergepoint-perl 0.04-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu resolute: libasync-mergepoint-perl 0.04-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- ubuntu stonking: libasync-mergepoint-perl 0.04-4 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms