[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