Belatedly, I've realised there's no need for cflowdepth to do
"context-free" tracematches if you have "let" pointcuts.
As an example, here is Neil's "lock/unlock must occur in
the same method" aspect written without cflowdepth.
Interestingly, for this micro-benchmark, it is almost twice
as fast as the cflowdepth version, despite the fact that
the thisJoinPoint objects will contain loads of spurious
information [we only need their identity]. So *if* we
had implemented an optimisation that only constructs those
parts of thisJoinPoint that are actually accessed, it's
quite likely that the thisJP version would be a lot faster
than the cflowdepth one.
Many thanks to Heffalump for fixing a bug that prevented
this yesterday!
-Oege
---------------------------------------------------------
import org.aspectj.lang.*;
aspect LockTraceMatch {
private static boolean debug;
private void debPrint(String s) {
System.out.println(s);
}
pointcut anyfunc() : execution( * *(..)) && !within(LockTraceMatch);
pointcut lock(A r) :
call(* A.lock()) && target(r);
pointcut unlock(A r) :
call(* A.unlock()) && target(r);
pointcut enclosingExec(JoinPoint jp) :
cflowbelow(anyfunc() && let(jp,thisJoinPoint));
//generates a memory leak warning
perthread tracematch(A r,JoinPoint jp) {
sym beforefunc before : anyfunc() && let(jp,thisJoinPoint) ;
sym afterfunc after : anyfunc() && let(jp,thisJoinPoint) ;
sym lock after : lock(r) && enclosingExec(jp) ;
sym unlock after : unlock(r) && enclosingExec(jp) ;
beforefunc lock afterfunc {
try {
throw new Exception("Unmatched lock");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
public class JPMain {
void f(A a) {
a.lock();
a.unlock();
}
void g(A a) {
a.lock();
}
void h(A a) {
a.lock();
f(a);
g(a);
a.unlock();
}
void k(A a) {
a.lock();
f(a);
g(a);
}
void test() {
A a = new A();
f(a);
g(a);
h(a);
k(a);
}
private static class TestThread extends Thread {
public void run() {
new JPMain() .
test();
}
}
public static void main(String args[]) {
//This runs fast
for (int i = 0; i < 10000; i++) {
new JPMain(). test();
}
//This starts out fast, but slows down consderably
for (int i = 0; i < 10000; i++) {
Thread t = new TestThread();
t.start();
}
}
}
class A {
A lock() {
System.out.println("A.lock");
return this;
}
void unlock() {
System.out.println("A.unlock");
return;
}
}
Received on Wed Dec 14 08:11:49 2005
This archive was generated by hypermail 2.1.8 : Wed Dec 14 2005 - 11:10:08 GMT