Bug 124175 - Nested join points
Summary: Nested join points
Status: RESOLVED WONTFIX
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-01-17 12:47 EST by Robert Onslow CLA
Modified: 2006-05-10 11:37 EDT (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Onslow CLA 2006-01-17 12:47:27 EST
Would it be a good idea to extend the pointcut syntax to be able to select all calls to method A where method A included calls to method B, which I don't think is possible with the current available pointcut syntax.
Comment 1 Wes Isberg CLA 2006-02-17 14:57:21 EST
No, but thanks for asking!  (This would be a good FAQ entry or mail-list question).  One of the nice properties of join points is that you can evaluate them without resorting to global analysis.  The call join point now can be evaluated based on the bytecode for the method invocation (there are different types of invocation, but we can ignore that here); you don't even need the actual target of the call that will be resolved at run time.  So this kind of thing would be bad for call or execution and other join points.  And it would be really impossible for call: since the called method is not known when the class is defined (for nonfinal instance methods), there's no way even to analyze what methods the called method calls.  (And if the compiler/weaver can't figure something out, I don't expect the user will, except in ad-hoc cases where they can trace the execution paths.)  By contrast, the scope modifiers (within/withincode) are determinable at the join point, even for call (and even for users *smile*).  

Another way to ask the question is to think about the use cases for what you're asking, and find out which ones you can't do using cflow pointcuts.  Is there a compelling use case?
Comment 2 Robert Onslow CLA 2006-02-21 09:55:47 EST
(In reply to comment #1)
Yes, I think there is a compelling use case. I have an object A whose methods a, b, c call methods d, e, f on object B. Each of a, b and c make multiple calls to d, e or f so it is necessary to preserve B's state against concurrent modification by other threads for the whole time that the thread is within a, b or c. This means locking object B against concurrent access from other threads while the thread is within the scope of a, b or c of A.

Now locking B while the thread is within d, e or f of B is trivial (simply define those methods as synchronized).

In order to lock B while the thread is within a, b or c of A is perfectly possible with manual calls to a lock() method on B upon entering a, b or c, performing the required calls to d, e and f on B, and finally making manual call to an unlock() method on B at the end of a, b or c

I can automate the requirement for the first manual call to lock() by implanting an internal call to lock() within methods d, e and f on B, (two successive calls to lock() by the same thread don't matter) but I cannot dispense with the need for a manual call to unlock() at the end of a, b or c. (Implanting a call to unlock() at the end of d, e, or f is no better than defining d, e or f as synchronized - B would be released while the thread is still within the scope of a, b or c)

JAspect could automate the calls to lock() and unlock() completely if it were possible to define a pointcut P which included any method on A which calls d, e or f on B - and then insert an advice "before" the poincut which called lock() on B, and an advice "after" the pointcut which called unlock() on B.

I don't believe that it is possible to solve this use case with cflow either.

May I reopen this request for 1 more consideration?

Thanks

Robert

> No, but thanks for asking!  (This would be a good FAQ entry or mail-list
> question).  One of the nice properties of join points is that you can evaluate
> them without resorting to global analysis.  The call join point now can be
> evaluated based on the bytecode for the method invocation (there are different
> types of invocation, but we can ignore that here); you don't even need the
> actual target of the call that will be resolved at run time.  So this kind of
> thing would be bad for call or execution and other join points.  And it would
> be really impossible for call: since the called method is not known when the
> class is defined (for nonfinal instance methods), there's no way even to
> analyze what methods the called method calls.  (And if the compiler/weaver
> can't figure something out, I don't expect the user will, except in ad-hoc
> cases where they can trace the execution paths.)  By contrast, the scope
> modifiers (within/withincode) are determinable at the join point, even for call
> (and even for users *smile*).  
> 
> Another way to ask the question is to think about the use cases for what you're
> asking, and find out which ones you can't do using cflow pointcuts.  Is there a
> compelling use case?
> 
Comment 3 Andrew Clement CLA 2006-02-23 03:37:15 EST
Can you not fix your problem by unlocking at the end of a,b,c ? So:

before(): execution(* B.*(..)) { B.lock(); }

after() returning: execution(* A.*(..)) { B.unlock(); }

If you need a particular B instance for the locks, use a stack-per-thread to stack what's been locked.

If you are asking for a solution to the more general case when you have no idea what the route to Bs methods are, I think you need predictive cflow: pcflow() - pcflow(p) matches at a join point where there exists a path to join points matched by p.  Gregor Kiczales mentioned it in a presentation he gave at a conference a little while back.  We have no plans to implement it in the short term.
Comment 4 Robert Onslow CLA 2006-02-23 04:58:07 EST
Thanks Andy.

Yes - I won't know the path to B's methods in advance, because I need to ensure that any method from any object which calls B's methods terminates in a B.unlock() call.

I guess predictive cflow looks good for this, so may I put my vote in for an implementation of this in JAspect?

Thanks

Robert
Comment 5 Wes Isberg CLA 2006-05-10 11:37:50 EDT
As Andy said, we're not going to implement predictive cflow any time soon.
stalebug