[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] If pointcut and side effects

So, if I understand that right, not even for a program like this is the behavior defined, since the "if" might be evaluated long before either the advice run?


public class C1 {
public static void main(String... args) {
C1 c1 = new C1();
c1.m();
}


public void m() {
System.out.println("m");
}
}

public aspect A1 {


static int x;


before() : call(void m())
{
System.out.println("before 1");
x = 5;
}


before() : call(void m()) && if(x==5) {
System.out.println("before 2");
}
} 

Output when I tested:

before 1
before 2
m

If barely anything can be said about when an if pointcut is evaluated, how can it be useful? A variable is assigned somewhere along the execution of the program, but of what interest is it to check it if one doesn't know when the check is going to happen?

Jon

On Jun 7, 2006, at 1:36 PM, Wes Isberg wrote:

Hi all -

Given pointcuts p1 and p2 matching the same join point, 

 before() : p1(){}
 before() : p2(){}

However, does that imply any order in which p1 and p2 are
evaluated?  
Are p2 evaluated first, last, or is it undefined?

The programming guide says only that the pointcut(s) will
match before the 
advice runs, so it is permitted e.g., for the pointcut to
be evaluated 
even at compile-time, if doing so would be correct.  So,
yes there are
no guarantees about the order of pointcut evaluation even
as between 
advice that are ordered by precedence.

Nor are there guarantees that, at a given join point with
two pieces of before 
advice that both use an if-pointcut that must be evaluated
at runtime, the 
more-precedent (first) if-pointcut-evaluation will run
first or the less-precedent 
(second) if-pointcut-evaluation will run after the first
if-pointcut-evaluation 
or advice. As I understand it, an implementation may
evaluate all pointcuts for
a join point before any advice is run.

The programming guide states the constraints necessary for
advice and pointcuts
to be usable for programmers, without stating additional
constraints that would
make it difficult for implementors of the language.  In
some cases that means 
telling programmers explicitly not to rely on
implementation regularities, e.g.,
that the Eclipse-based implementation of AspectJ follows
certain rules about
when if-pointcuts are evaluated.

That's the policy behind the silence or caveats on certain
points in the programming 
guide, but it's still helpful to talk about what should be
the case.  The best
discussions are motivated (imho) by specific use-cases
rather than academic 
curiosity.

For example, this has come up in the past for if-pointcut
with respect to
semi-fixed results:  Should AspectJ take responsibility for
caching/inlining
results of a static operation, e.g., to check when we are
debugging?  
Can AspectJ take a single pointcut designator, e.g.,

  if(Debug.debugging())

that is referenced in multiple pieces of advice on the same
join point, and
evaluate it only once?  Or should it do so for each advice?
 Does the answer
change when all pointcuts reference the same named
pointcut, e.g.,

  pointcut debugging(): if(Debug.debugging());

The answer for Java is relatively clear: evaluate it each
time.  And since 
the programmer can refactor an if-pointcut statement to
cache results, 
we can punt and leave it to the programmer to manage this.


As another example:  For pointcuts other
than if-pointcuts, one might assume that the results for a
given PCD should be
the same for all advice, even if the pointcut is dynamic.
 E.g., that the
target is a Runnable.  But then you realize that the target
can be changed,
so, e.g., when the join point starts to run the target is
not Runnable, but then
after some around advice has changed the target, it is
Runnable.  That would seem
to imply that the results can't be cached for any pointcut
designator if the
results can change (under expected use).

This is not just academic.  Some use-cases involve
replacing the actual target
with an instrumented proxy or mock object, with advice
implementing different
behavior when instrumented or mock objects are at play, so
advice interaction
can depend on the behavior of evaluated pointcuts. 

That's am example where there is a real issue that is not
addressed explicitly
by the programming guide but which should be.  It's also an
area where our
Eclipse-based implementation of AspectJ has (had) some
inconsistencies. 
If, e.g., a critical/analytical user worked out the scope
of that question and 
presented the issue for discussion framed by a use-case in
code, it would be 
a great service to the AspectJ community.

Thanks -
Wes

------------Original Message------------
From: "Jon S. Baekken" <jbaekken@xxxxxxxxxxxx>
Date: Wed, Jun-7-2006 12:35 PM
Subject: Re: [aspectj-users] If pointcut and side effects
I'm confused myself about what exactly that means, but this
is what the programming guide says (appendix B, advice
semantics):


At a particular join point, advice is ordered by
precedence.


A piece of around advice controls whether advice of lower
precedence will run by calling proceed. The call to proceed
will run the advice with next precedence, or the
computation under the join point if there is no further
advice.


A piece of before advice can prevent advice of lower
precedence from running by throwing an exception. If it
returns normally, however, then the advice of the next
precedence, or the computation under the join pint if there
is no further advice, will run.


Running after returning advice will run the advice of next
precedence, or the computation under the join point if
there is no further advice. Then, if that computation
returned normally, the body of the advice will run.


Running after throwing advice will run the advice of next
precedence, or the computation under the join point if
there is no further advice. Then, if that computation threw
an exception of an appropriate type, the body of the advice
will run.


Running after advice will run the advice of next
precedence, or the computation under the join point if
there is no further advice. Then the body of the advice
will run.


Given that, it seems to me, execution order is defined in
terms of precedence, and that if some after advice has
precedence over some before advice, the after advice will
actually start "running" before the join point, but
immediately implicitly call the advice with the 2nd highest
precedence, and so on. At some point the execution comes
back to this after advice, which now executes its body. In
effect, it is executing after the join point.


This model works well in explaining the rules of precedence
among advice, and how for example an around advice not
calling proceed might sometimes stop an after advice from
running, while sometimes it will not, depending on their
relative order:


void around() : p() {...}
after() : p() {...}


(after takes precedence and around not calling proceed
won't affect its execution)


after() : p() {...}
void around() : p() {...}


(around takes precedence and not calling proceed will
result in the after advice not running)


If it reflects the actual implementation, I don't know.


Jon


On Jun 7, 2006, at 12:17 PM, Eric Bodden wrote:


before() : p1() {...}


after() : p2() {...}


Here, the after advice has precedence over the before
advice, so
according to the appendix B in the programming guide the
after advice
should run first (although its body will of course run
last).


Now you've gotta explain to us what's the difference
between running an
advice an running its body, I guess... I am confused. 


before-advice run of course before the joinpoint and
after-advice after
the joinpoint. This has nothing to do with prescedence.


Eric


--
Eric Bodden
Sable Research Group, McGill University
Montreal, Canada




_______________________________________________
aspectj-users mailing list


_______________________________________________ 
aspectj-users mailing list 

_______________________________________________
aspectj-users mailing list