I would suggest you work with die instead though - that will work with nested transactions and require fewer hoop jumps. You can then also easily add some more error checking:sub commit () { ($T || ${ caller() . '::T' })->commit; goto END_XACTION; } sub rollback () { ($T || ${ caller() . '::T' })->rollback; goto END_XACTION; } sub transaction (&) { my ($block) = @_; local $T = ${ caller() . '::T' } or croak "\$T not set"; local $@; eval { $T->begin_work; $block->(); }; $@ ? rollback : commit; END_XACTION: die $@ . "commit not safe after errors, transaction r +olled back" if $@; }
sub commit { require Carp; Carp::croak("Can't commit outside a transaction"); } sub rollback { require Carp; Carp::croak("Can't rollback outside a transaction"); } sub transaction (&) { my ($block) = @_; my $caller = caller(); local *{"${caller}::commit"} = sub { die "!COMMIT\n" }; local *{"${caller}::rollback"} = sub { die "!ROLLBACK\n" }; local $@; eval { $T->begin_work; $block->(); }; if(!$@ or $@ eq "!COMMIT\n") { ${"${caller}::T"}->commit; } elsif($@ eq "!ROLLBACK\n") { ${"${caller}::T"}->rollback; } else { ${"${caller}::T"}->rollback; require Carp; Carp::croak($@ . "commit not safe after errors, transaction ro +lled back"); } }
Makeshifts last the longest.
In reply to Re: RFC: Transactions.pm
by Aristotle
in thread RFC: Transactions.pm
by Juerd
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |