[aspectc-user] args() question & aspectof question

Olaf Spinczyk Olaf.Spinczyk at informatik.uni-erlangen.de
Wed Apr 13 14:17:34 CEST 2005


Hello Hans,

Hans VB wrote:
> Hi,
> 
> I have two questions :
> 
> 1. The args() function not only selects join points but also stores 
> context information. Is it correct to say the name of the argument can 
> differ between the pointcut- and advice-declaration because of the 
> existance of this context information? Am i correct in presuming this 
> 'context information' is added to poincuts which use args() ? I'm a bit 
> in doubt about the actual meaning of 'context information'.
> 
> I take the example from the ac++ manual where 'name' is replaced by 
> 'username' in the advice-declaration :
> pointcut new_user(const char *name) = execution ("void login(...)") && 
> args(name);
> advice new_user(username) : before(const char* username) { ... }

args() does not nescessarily bind context information. For example, 
args("const char*") only matches (or "selects") join points with one 
argument of type "const char *". You can also use wildcards for matching.

Additionally you can use args() to "expose context information". 
"Context information" is information that is available at a join point 
and that should be transported to the advice code. For example, the 
actual argument values of a function execution join point are context 
information. The pointcut function args() can be used to transport this 
information to advice code that affects this join point:

advice execution(..) && args(x) : before (const char *x) { .. }

Here args(x) fulfills two purposes: it filters join points, i.e. only 
join points with one argument of type "const char *" are selected 
(because the type of 'x' is "const char *"). The argument of the join 
point is bound to the advice parameter 'x'.

If args is used in the definition of a named pointcut function, the 
pointcut function becomes a pointcut function that provides context 
information:

pointcut one_string_arg(const char *s) = args(s);

Here 's' is a context variable which is bound to context information 
from the join point. In this case the first and only argument.

With this definition of one_string_arg you could, for instance, replace 
args(x) with one_string_arg(x) in the example above.

I hope that it more clear now.

> 2. In the ac++ manual the following (slightly modified) example is given 
> concering aspect instantiation :
> aspect ThreadCounter {
>  advice "Thread" : ThreadCounter m_instance;
>  static ThreadCounter *aspectof() {
>    return tjp->target()->m_instance;
>  }
> };
> 
> In a similar example (though in a completely different scenario than 
> with these Threads) I got many errors:
> cannot convert `AnAspect' to `AnAspect*' in return.
> (it seems always 2 more of these errors more than I have 
> advice-declarations).
> I solved this by changing this :
>    return *(tjp->target()->m_instance);
> It works but only if there is no advice from global functions (like 
> main()). If there is advice for main() I get an error: `void*' is not a 
> pointer-to-object type. (this error i also got in the first case btw)
> 
> Can someone tell me what I could be doing wrong here ?
> 
> Thanks in advance,
> Hans

You can use aspectof() to implement various placement schemes for your 
aspect instance(s). The default (an aspect is always a singleton - a 
global object) is sufficient in many cases, but some implementation can 
benefit from a more flexible handling of aspect instances. By using 
introductions you can introduce your aspect instance(s) wherever you 
like as long as you provide an aspectof() function that is able to 
return a pointer to an aspect instance for every join point from which 
advice of this aspect might be invoked. Of course, the implementation of 
aspectof() has to return an object of the correct type. In your example 
I would suppose that

return &(tjp->target()->m_instance);

would be the correct implementation.

As you need information about the current join point in order to 
associate the right aspect instance for advice execution, the 
Joinpoint-API can be used in aspectof(). In your example the 
tjp->target() function is used to find the target object of a call. The 
problem is that tjp->target() is only able to return a valid object 
pointer (!= NULL) at call join points where a (non-static) member 
function of a class is called or at execution join points where a 
non-static member function is executed. For main() tjp->target() returns 
NULL and the type is void*.

In summary: your aspectof() implementation does not provide a pointer to 
an aspect instance for non-class member function execution join points. 
You either have to change the implementation or avoid to match 'main()' 
in your pointcut expressions of this aspect.

If you decide, for instance, that a global aspect instance should be 
used in the case that tjp->target() yields NULL, the implementation 
would look like this:

static ThreadCounter *aspectof() {
   static ThreadCounter instance_for_non_member_functions;
   return tjp->target () ? &(tjp->target()->m_instance) :
                           &instance_for_non_member_functions;
}

Best regards,

Olaf



More information about the aspectc-user mailing list