Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
RE: [aspectj-users] if and loop pointcuts

Diana,

I agree with Andrzej that this would be best handled with a refactoring. Writing advice that counts the number of accesses seems quite brittle to me, e.g., later on you add one more access and forget to update your aspect, which releases the lock too early, leading to a very rare race condition. 

I do think there would be value in a loop pointcut, especially with the new J2SE 1.5 for constructs that let you explicitly loop over a collection or array (e.g., for (Object o : c) { operation(o); } ). The situations where a loop pointcut would have been useful for me were cases where I need to write advice on loop execution and also on execution of each iteration. E.g., I had to refactor

void originalMethod() {
    ...
    for (int i=0; i<recs.length; i++) {
      /* process recs[i] */
    }
}

into

void originalMethod() {
    ...
    processRecords(recs, <lots of state>);
}

void processRecords(Record[] recs, ...) {
    for (int i=0; i<recs.length; i++) {
        processRecord(recs[i], <lots of state>);
    }
}

void processRecord(Record r, ...) {
}

processRecords() demarks the start and end of a transaction. I also wanted to log the event that I had started and finished processing a record (after every 1000) in processRecord and log the event that I had finished committing a transaction in processRecords. So I needed to refactor into 2 methods. I'm happy with refactoring the the loop into a method (processRecords), but I think it would be better to be able to write advice on binding the next loop value, not extracting processRecord as a method.

I'd like to write something like
pointcut processRecord(Record[] recs, Record r) : iterating() && target(r) && recs;
before(Record[] recs, Record r) : processRecord(recs, r) { ... }

If you are using an Iterator, you can write an aspect that tracks iteration, but it is less convenient to use this than a real pointcut, and it doesn't let you track the end of the iteration over an element or the end of the entire iteration:

public abstract aspect TrackIteration {
    private Map openIterations = new WeakHashMap(); // automatically remove completed iterators

    public abstract pointcut scope();
    public pointcut startIteration(Collection c) : 
        call(Iterator Collection.iterator()) && target(c) && scope();
    public pointcut iterating(Iterator it): call(Object Iterator.next()) && scope();

    after(Collection c) returning (Iterator it) : startIteration(c) {
        openIterations.put(it, c);
        startedIteration(it, c);
    }

    after(Iterator it) returning (Object o) : iterating(it) {
        Collection c = (Collection)openIterations.get(it);
        iterated(it, o, c);
    }

    // advice to purge 

    // methods to override, or advise
    public void startedIteration(Iterator it, Collection c) {
    }

    public void iterated(Iterator it, Object o, Collection c) {
    }
}

Ron Bodkin
Chief Technology Officer
New Aspects of Security
m: (415) 509-2895

> ------------Original Message-------------
> From: Diana Szentivanyi <diasz@xxxxxxxxxx>
> To: aspectj-users@xxxxxxxxxxx
> Date: Wed, Aug-13-2003 2:05 AM
> Subject: RE: [aspectj-users] if and loop pointcuts
> 
> >At the time we designed the language, we could think of no compelling
> >use cases for pointcuts related to if and do. So we didn't spend any
> >time thinking about them.
> >
> >Since then I've heard a couple of examples of when these might be useful,
> >most having to do with coverage problems.
> >
> >I'm starting to think something like this could be added to the language
> >and prove useful. But I don't see it yet.  One problem is designing the
> >pointcuts to be stable. Unstable pointcuts are those that are defined in
> >terms that are vulnerable to small seemingly unrelated changes to the program.
> >The classic example is the line number pointcut, that says something like when
> >executing expressions or statements at this line number. 
> >
> >Could you give an example of the kind of pointcut and advice you would like 
> >to write?
> >
> 
>   I need to detect when a field is accessed the last time in a method. For this, 
> I am given the total number of accesses (get/set) to that field; during 
> execution of the method I count the number of accesses by using get and set 
> pointcuts. This works fine as long as I do not have if's and loops where in some 
> cases is not known beforehand how many times the field is accessed. 
>   Example: I want to know when the last access to "a" happens. "a" is accessed 
> in the method below, a number of times given by the formula: nr=1+1+(0|1)+(0|?) 
> = 2+(0|1)+(0|?). 
>   The (0 or 1) accesses is given by the "else" branch of the "if", and the (0 or 
> more) accesses is given by the "while" loop (2 accesses in line 8). Of course, 
> it is possible to have inner loops, or inner if statements in the if or loops.
>    
>   void some_method(){
>     1:b=r+4;
>     2:a=b+15/c;
>     3:if(a<20)
>     4:  c=34;
>     5:else    
>     6:  a=18;
>     7:while(b<30){
>     8: if(d<20) 
>     9:  a=a-b;
>    10: else
>    11:  d--;
>    12: b++;
>    13:}
>   }  
>   
>   What would solve my problem is the following: 
>     * I am given the above formula for the number of accesses: 2+(0|1)+(0|?) 
> which can be written as 2+1+1
>     * The aspect language with the pointcuts helps me detect when the control 
> flow left the if or the loop, when the counter of accesses is incremented with 
> 1; of course, after the accesses in lines 2 and 3 the counter is incremented 
> with 1 in the plain get/set based pointcut advices; when the counter reaches the 
> value 4 (2+1+1) it means that the last access to "a" was detected. 
>     
>     So, the pointcuts and advices I would write look as follows:
>     
>     pointcut in_if(): ...(if_statement);
>     pointcut in_loop(): ...(loop);
>     pointcut _a_in_if_loop(): (get(int a)||set(int a)) && 
> (cflow(in_if)||cflow(in_loop));
>     pointcut _a_normal(): (get(int a)||set(int a)) 
> &&cflow(in_if)&&!cflow(in_loop);
>     
>     after(): in_if(){
>     	counter_access_a++;
>     }
>     
>     ..................
>     
>     after(): _a_normal(){ counter_access_a++;}
>     
>     
>     I am aware that it is possible that the field is not at all accessed in the 
> if (for example in case a<20) or in the loop (in case d>20 in every iteration) 
> and then some time can pass between the field is accessed last and this fact is 
> detected. 
>     
>     
>               Thanks a lot,
>                 Regards,
>                   Diana.
>      
>   
> 
> _______________________________________________
> aspectj-users mailing list
> aspectj-users@xxxxxxxxxxx
> http://dev.eclipse.org/mailman/listinfo/aspectj-users
> 


Back to the top