Hack #88. Clean Up at the End of a Scope

Execute your cleanup code, no matter how you exit a scope.

Successful programs are robust. Even if errors happen, the programs can adapt, continuing if possible, but always exiting cleanly and sensibly.

Robust programs often need to guarantee that some sort of cleanup happens sometimes, whether that's closing spawned programs properly, flushing buffers, removing temporary files, or giving up an exclusive resource. Some programming languages and platforms provide ways to ensure that your cleanup code always runs. Perl doesn't—but it does provide the hooks to make it possible.

The Hack

Imagine that you have to write a program that processes and analyzes records from a database. The processing isn't idempotent, so you need to keep track of the most recent record processed. You can assume that the record ids increase monotonically. However, admins can interrupt the program as necessary, as the task has a low priority. You want to make sure that, no matter what happens, you always record the id of the most-recently processed item.

Use Scope::Guard and a closure to schedule an end-of-scope operation:

use Scope::Guard; sub process_records { my $records = fetch_records( ); my $last_rec = 0; my $cleanup = sub { cleanup( $last_rec ) if $last_rec }; my $guard = Scope::Guard->new( $cleanup ); for my $record ( @$records ) { process_record( $record ); $last_rec = $record; } } sub cleanup { my $record = shift; # mark record as last record successfully ...

Get Perl Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.