Aspect

 view release on metacpan or  search on metacpan

lib/Aspect/Advice/Around.pm  view on Meta::CPAN

			# Is this a lexically scoped hook that has finished
			goto &\$original if $MATCH_DISABLED;

			# Apply any runtime-specific context checks
			my \$wantarray = wantarray;
			local \$Aspect::POINT = bless {
				type         => 'around',
				pointcut     => \$pointcut,
				original     => \$original,
				sub_name     => \$name,
				wantarray    => \$wantarray,
				args         => \\\@_,
				return_value => \$wantarray ? [ ] : undef,
				topic        => \\\$_,
			}, 'Aspect::Point';

			# Can we shortcut the advice code
			goto &\$original unless $MATCH_RUN;

			# Run the advice code
			SCOPE: {
				local \$_ = \$Aspect::POINT;
				Sub::Uplevel::uplevel(
					1, \$code, \$Aspect::POINT,
				);
			}

			# Return the result
			return \@{\$Aspect::POINT->{return_value}} if \$wantarray;
			return \$Aspect::POINT->{return_value};
		};
END_PERL
		$self->{installed}++;
	}

	# If this will run lexical we don't need a descoping hook
	return unless $lexical;

	# Return the lexical descoping hook.
	# This MUST be stored and run at DESTROY-time by the
	# parent object calling _install. This is less bullet-proof
	# than the DESTROY-time self-executing blessed coderef
	return sub { $out_of_scope = 1 };
}

# Check for pointcut usage not supported by the advice type
sub _validate {
	my $self     = shift;
	my $pointcut = $self->pointcut;

	# Pointcuts using "throwing" are irrelevant in before advice
	if ( $pointcut->match_contains('Aspect::Pointcut::Throwing') ) {
		return 'The pointcut throwing is illegal when used by around advice';
	}

	# Pointcuts using "throwing" are irrelevant in before advice
	if ( $pointcut->match_contains('Aspect::Pointcut::Returning') ) {
		return 'The pointcut returning is illegal when used by around advice';
	}

	$self->SUPER::_validate(@_);
}

1;

=pod

=head1 NAME

Aspect::Advice::Around - Execute code both before and after a function

=head1 SYNOPSIS

  use Aspect;
  
  around {
      # Trace all calls to your module
      print STDERR "Called my function " . $_->sub_name . "\n";
  
      # Lexically alter a global for this function
      local $MyModule::MAXSIZE = 1000;
  
      # Continue and execute the function
      $_->run_original;
  
      # Suppress exceptions for the call
      $_->return_value(1) if $_->exception;
  
  } call qr/^ MyModule::\w+ $/;

=head1 DESCRIPTION

The C<around> advice type is used to execute code on either side of a
function, allowing deep and precise control of how the function will be
called when none of the other advice types are good enough.

Using C<around> advice is also critical if you want to lexically alter
the environment in which the call will be made (as in the example above
where a global variable is temporarily changed).

This advice type is also the most computationally expensive to run, so if
your problem can be solved with the use of a different advice type,
particularly C<before>, you should use that instead.

Please note that unlike the other advice types, your code in C<around> is
required to trigger the execution of the target function yourself with the
C<proceed> method. If you do not C<proceed> and also do not set either a
C<return_value> or C<exception>, the function call will return C<undef>
in scalar context or the null list C<()> in list context.

=head1 AUTHORS

Adam Kennedy E<lt>adamk@cpan.orgE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright 2010 - 2013 Adam Kennedy.

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



( run in 1.360 second using v1.01-cache-2.11-cpan-d7f47b0818f )