package Evo::Guard;
use Evo::Base -strict;

sub new {
  my $class = shift;
  Carp::croak "You have to save Evo::Guard object to the variable"
    unless defined wantarray;
  bless {@_}, $class;
}

sub DESTROY {
  my $self = shift;

  if ($self->{error}) {
    my $onerror = delete $self->{error};
    my $err     = $@;
    $err and eval { $onerror->($err); 1 } || Carp::carp $@;
  }

  (delete $self->{always})->() if $self->{always};
}

1;

# ABSTRACT: A guard

__END__

=pod

=encoding UTF-8

=head1 NAME

Evo::Guard - A guard

=head1 VERSION

version 0.0158

=head1 SYNOPSIS

  use Evo::Base -strict;
  use Evo::Guard;

  eval {
    my $guard = Evo::Guard->new(
      error  => sub { say "ERROR cleanups" },
      always => sub { say "Always cleanups" }
    );
    die "Error";
  };

=head2 Arguments

=head1 DESCRIPTION

Executes a code when no refs are pointed to this object.
The behavoiur is similar to L<Guard/"guard">, but this module is pure
perl (and about 70-80% slower) and covers more cases.

It can be used to do some cleanups no matter was exception thrown or not.
Or it can do something usefull only on exceptions
Or it can do both

=head1 METHODS

=head2 new

Creates a guard object. It will raise an exception if you forget to save it
in somewhere.

If an error callback will cause an exception (but this is surely a bug in 
your code), always callback will be executed too

=head3 error

A callback that will be executed only if an unhandled exception was trown in the
same scope

=head3 always

This callback will be executed no matter was exception thrown or not

=head1 AUTHOR

alexbyk.com

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by alexbyk.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
