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 rolled back" if $@; }