2020/12/06

2020 Perl Advent Calendar - Day 6

<< First | < Prev | Next >

By now we are beginning to build the impression that writing asynchronous code using async/await syntax looks and feels much neater, because its structure is much more similar to that of equivalent synchronous code which would do the same task. Aside from functions being marked with async and expressions having await at strategic points in them, the code all looks exactly the same as you'd find in a simpler synchronous style.

At this point I'm going to continue following the overall theme and topic of each of the original Futures blog post articles, but using real examples of code from real modules on CPAN (or at least, slightly reworded ones). These should give a more varied and interesting sense of actual code, than the rather artifical examples centered around the HTTP GET examples we have used so far.

The original day 10 article hinted at some ways to structure asynchronous code code using futures to have conditional parts to it. With async/await syntax no special considerations need to be taken. All of the usual conditional code flow styles - such as if blocks or shortcircuit evaluation - will apply just fine.

For example, this method from a module which communicates with an attached hardware device, implements a cache around reading a certain data register from it.

use Future::AsyncAwait;

async sub _read { ... }

async sub _cached_read_TIMING
{
    my $self = shift;
    
    return $self->{TIMINGbytes} //= await $self->_read(REG_TIMING, 1);
}

This would have been quite awkward to write using plain futures and ->then chaining, but using async/await and the ability to place the await expression anywhere makes this much simpler. If the key on $self is already defined then its value is returned immediately. If not, the entire asynchronous method is suspended while it performs a read operation on the underlying hardware, and when the result is available that is returned, as well as being stored into the object for next time.

The original day 11 article introduced the ->transform method, which tries to neaten certain forms of sequencing operation which calculate and return a new value based on the value returned by an asynchronous operation. This again is much simpler using async/await syntax, because we can put the await expression anywhere in the code.

For example, this method asynchronously fetches a byte string from the attached hardware, then unpacks it into an integer using the unpack function.

use Future::AsyncAwait;

async sub read_data0
{
    my $self = shift;
    
    return unpack "S<", await $self->_read(REG_DATA0, 2);
}

Here we wait for the bytes to be read from the hardware, and when they arrive pass them into the unpack core operator, and return that result.

<< First | < Prev | Next >

No comments:

Post a Comment