+ All Categories
Home > Documents > AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel...

AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel...

Date post: 24-Dec-2015
Category:
Upload: dale-lester
View: 227 times
Download: 0 times
Share this document with a friend
Popular Tags:
37
AOP and Aspect C ++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk
Transcript
Page 1: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

AOP and Aspect C++

presentation by Igor Kotenkov

based on presentation by

Andreas Gal, Daniel Lohmann and Olaf Spinczyk

Page 2: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Contents

• AOP with pure C++

• AspectC++

• AspectC++ Tool Support

• Summary

Page 3: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.
Page 4: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.
Page 5: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Templates

• Templates can be used to construct generic code.• To actually use the code, it has to be instantiated.• As preprocessor directives:

– templates are evaluated at compile time

– they do not cause any direct time overhead (if applied properly)

Templates are typically used to implement generic abstract data types.

Page 6: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

AOP with templates

• Templates allow us to encapsulate aspect code independently from the component code.

• Aspect code is “woven into” the component code by instantiating those templates.

class Queue {

void enqueue(Item *item) {

// adding item to the queue

}

Item *dequeue() {

// remove item from the queue

}

};

temeplate <class Q>

Counting_Aspect : public Q {

int counter;

public:

void enqueue(Item *item) {

Q::enqueue(item); counter++;

}

Item *dequeue() {

Item *res = Q::dequeue(item);

if (counter > 0) counter--;

return res;

}

// this method is added to the component code

int count() const {return counter;}

};

Page 7: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Weaving

We can define a type alias (typedef) that combines both, component and aspect code:

typedef Counting_Aspect<Queue> CountingQueue;

int main() {

CountingQueue q;

q.add(…);

}

Page 8: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Combining Aspects

Weaving with multiple aspects:

typedef Exception_Aspect<Counting_Aspect<Queue> > ExceptionsCountingQueue;

or typedef Counting_Aspect<Exception_Aspect<Queue> > ExceptionsCountingQueue;

for counting first and then – checking for exceptions.

Implementation of the aspects should be independent of ordering, so it will be no problem with either ordering we will apply.

Page 9: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Limitations

• Joinpoint types– no distinction between function call and execution;– no advice for attribute access;– no advice for private member functions.

• Quantification– no flexible way to describe the target components;– applying the same aspect to classes with different interfaces is

impossible or ends with excessive template metaprogramming.

• Scalability– the wrapper code can easily outweigh the aspect code;– explicitly defining the aspect order for every affected class;– makes code hard to understand and debug.

“AOP with pure C++ is like OOP with pure C”

Page 10: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Conclusions

• C++ templates can be used for separation of concerns in C++ code without special tool support

• However, the lack of expressiveness and scalability restricts these techniques to projects with:– only small number of aspects;

– few or no aspect interactions;

– aspects with a non-generic nature;

– component code that is “aspect-aware”.

Page 11: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Aspect C++

• Basic features within Queue example– aspect, advice, execution, call– introduction– joinpoints, pointcut expressions

• Advanced concepts– the Joinpoint API– abstract aspects and aspect inheritance– aspects ordering– aspect instantiation

• Summary

Page 12: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

ElementCounter aspect

aspect ElementCounter {

int counter;

ElementCounter() {

counter = 0;

}

advice execution(“% util::Queue::enqueue(…)”) : after() {

++counter;

printf(“ Aspect ElementCounter: # of elements = %d\n”, counter);

}

advice execution(“% util::Queue::dequeue(…)”) : after() {

if (counter > 0) --counter;printf(“ Aspect ElementCounter: # of elements = %d\n”, counter);

}};

Introducing new aspect.An aspect starts with word aspectand is syntactically much like a class.

Like a class, an aspect can define datamembers, constructors and so on.

Page 13: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

ElementCounter aspect

aspect ElementCounter {

int counter;

ElementCounter() {

counter = 0;

}

advice execution(“% util::Queue::enqueue(…)”) : after() {

++counter;

printf(“ Aspect ElementCounter: # of elements = %d\n”, counter);

}

advice execution(“% util::Queue::dequeue(…)”) : after() {

if (counter > 0) --counter;printf(“ Aspect ElementCounter: # of elements = %d\n”, counter);

}};

Giving after advice This pointcut expression denoteswhere the advice shoud be given.

Page 14: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Introduction

• The aspect is not the ideal place to store the counter, because it is shared between all Queue instances

• Ideally, counter becomes a member of Queue• So, we will:

– move the counter into Queue by introduction;– expose context about the aspect invocation to access the

current new instance.

Page 15: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Introduction - continueaspect ElementCounter {private:

advice “util::Queue” : int counter;public:

advice “util::Queue” : int count {return counter;} const

ElementCounter() {counter = 0;

}

advice execution(“% util::Queue::enqueue(…)”) && that(queue) : after(util::Queue& queue) {++queue.counter;printf(“ Aspect ElementCounter: # of elements = %d\n”, queue.count());

}advice execution(“% util::Queue::dequeue(…)”) && that(queue) : after(util::Queue& queue) {

if (queue.count() > 0) --queue.counter;printf(“ Aspect ElementCounter: # of elements = %d\n”, queue.count());

}advice execution(“% util::Queue::Queue(…)”) && that(queue) : before(util::Queue& queue) {

queue.counter = 0;}

};

Introducing a public method to read the counter

Introduces a new data member counterinto all classes denoted by pointcut “util::Queue”

A context variable queue is bound to that.It has to be an util::Queue.

It is used to access the current instance

// within the constructor advice we ensure, that counter gets initialiazed

Page 16: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Joinpoints

• A joinpoint denotes a position to give advise:– Code joinpoint (control flow):

• execution of a function

• call to a function

– Name joinpoints• a named C++ program entity (identifier)

• class, function, method, type namespace

• Joinpoints are given by pointcut expressions– a pointcut expression describes a set of joinpoints

Page 17: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Pointcut Expressions

• Pointcut expressions are made from:– match expressions, e.g. “% util::Queue::enqueue(…)”

• are matched against C++ program entities (name joinpoints)• support wildcards

– pointcut functions, e.g. execution(…), call(…), that(…), within(…), cflow(…)

• execution: all points in the control flow, where a function is about to be executed (code joinpoints)

• call: all points in the control flow, where a function is about to be called (code joinpoints)

• Pointcut functions can be combined– using logical connectors: &&, ||, !– example:

• call(“% util::Queue::enqueue(…)”) && within(“% main(…)”)• !cflow(execution(“% util::~Queue()”))

Page 18: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Advice

• Advice to functions– before advice

• advice code is executed before the original code• advice may read/modify parameter values

– after advice• advice code is executed after the original code• advice may read/modify return value

– around advice• advice code is executed instead of the original code• original code may be executed explicitly: tjp->proceed()

• Introductions– additional methods, data members, etc. are added to the class– can be used to extend the interface of a class or namespace

Page 19: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Error Handling

• We want to check the following constraints:– enqueue() is never called with a NULL item– dequeue() is never called on an empty queue

• In a case of an error an exception should be thrown

• To implement this the advice needs an access to– the parameter passed to enqueue()– the return value returned by dequeue()

Page 20: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

ErrorExceptionnamespace util {

class QueueInvalidItemError {};

class QueueEmptyError {};

}

aspect ErrorException {

advice execution(“% util::Queue::enqueue(…)”) && args(item) : before(util::Item* item) {

if (item == NULL) throw util::QueueInvalidItemError();

}

advice execution(“% util::Queue::dequeue(…)”) && result(item) : after(util::Item* item) {

if (item == NULL) throw util::QueueEmptyError();

}

};

Page 21: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Thread Safety

• Protect the queue by a mutex object• To implement this, we need to

– introduce a mutex variable into class Queue– lock it before execution of enqueue/dequeue– unlock it after execution of enqueue/dequeue

• The implementation should be exception safe– in the case of exception the “after” advice should called also– solution: around advice

Page 22: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

LockingMutexaspect LockingMutex {

advice “util::Queue” : os::Mutex lock;

pointcut sync_methods() = “% util::Queue::%queue(…)”;

advice execution(sync_methods()) && that(queue) : around(util::Queue& queue) {queue.lock.enter();try { tjp->proceed();} catch(…) { queue.lock.leave(); throw;}queue.lock.leave();

}};

Page 23: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Queue Example Summary

• The Queue example has presented the most important features of the AspectC++ language– aspect, advice, joinpoint, pointcuts, introduction, etc.

• Additionally, AspectC++ provides some more advanced concepts and features– to increase the expressive power of aspectual code– to write broadly reusable aspects– to deal with aspect interdependence and ordering

Page 24: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Advanced Concepts

• The Joinpoint API– provides a uniform interface to the aspect invocation context

• Abstract Aspects and Aspect Inheritance

• Aspects Ordering– allows to specify the invocation order of multiple aspects– Important in the case of inter-aspect dependencies

• Aspect Instantiation– allows to implement user-defined aspect instantiation models

Page 25: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

The Joinpoint API

• Inside the advice body, the current joinpoint context is available via the implicitly passed tjp variable:

advice … {

struct JoinPoint {

} *tjp; // implicitly available in advice code

• You have already seen how to use tjp: tjp->proceed() to execute the original code in around advice

• The joinpoint API provides a rich interface– to expose context independently of the aspect target– this is especially useful in writing reusable aspect code

Page 26: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

The Joinpoint APIstruct JoinPoint {

// result type of a functiontypedef JP-specific Result;// object type (initiator)typedef JP-specific That;// object type (receiver)typedef JP-specific Target;// returns the encoded type of the joinpoint// (result conforms with C++ ABI V3 spec)static AC::Type type();// the same for resultstatic AC::Type resulttype();// the same for an argumentstatic AC::Type argtype(int n);// returns an unique id for this joinpointstatic unsigned int id();// returns joinpoint type of this joinpoint// (call, execution, …)static AC::JPType jptype(); };

// number of arguments of a function callstatic int args();// textual representation of this joinpointstatic const char* signature();// returns a pointer to the n’th argument// value of a function callvoid* arg(int n);// returns a pointer to the result value of a// function callResult* result();// returns a pointer to the object initiating a call That* that();// returns a pointer to the object that is target of a call

Target* target();// executes the original code in an around advicevoid proceed();// returns the runtime action objectAC::Action& action();

Page 27: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Abstract Aspects and Inheritance

• Aspects can inherit from other aspects– reusing aspect definitions– overriding methods and pointcuts

• Pointcuts can be pure virtual– postponing the concrete definition to derived aspects– an aspect with a pure virtual pointcut is called abstract aspect

• Common usage: resusable aspect implementation– Abstract aspect defines advice code, but pure virtual pointcuts– Aspect code uses the joinpoint API to expose context– Concrete aspect inherits the advice code and overrides

pointcuts

Page 28: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Abstract Aspects and Inheritance

#include “mutex.h”aspect LockingA {

pointcut virtual sync_classes() = 0;pointcut virtual sync_methods() = 0;

advice sync_classes() : os::Mutex lock;

advice execution(sync_methods()) : around() {tjp->that()->lock.enter();try { tjp->proceed();} catch(…) { tjp->that()->lock.leave(); throw;}tjp->that()->lock.leave();

}};

Page 29: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Abstract Aspects and Inheritance

#include “mutex.h”aspect LockingA {

pointcut virtual sync_classes() = 0;pointcut virtual sync_methods() = 0;

advice sync_classes() : os::Mutex lock;

advice execution(sync_methods()) : around() {tjp->that()->lock.enter();try { tjp->proceed();} catch(…) { tjp->that()->lock.leave(); throw;}tjp->that()->lock.leave();

}};

#include “LockingA.ah”

aspect LockingQueue : public LockingA {pointcut sync_classes() = “util::Queue”;pointcut sync_methods() = “% util::Queue::%queue(…)”;

};

Page 30: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Aspect Ordering

• Aspects should be independent of other aspects– however, sometimes inter-aspect dependencies are unavoidable– example: locking should be activated before any other aspect

• Order advice– the aspect order can be defined by order advice

advice pointcut-expr : order(high, …, low)

– different aspect orders can be defined for different pointcuts

• Example:advice “% util::Queue::%queue(…)” : order(“LockingQueue”, “%” && ! “LockingQueue”)

Page 31: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Aspect Instantiation

• Aspects are singeltons by default– aspectof() returns pointer to one-and-only aspect instance

• By overriding aspectof() this can be changed– e.g. one instance per client or one instance per thread

aspect MyAspect {

// …

static MyAspect* aspectof() {

static __declspec(thread) MyAspect* theAspect = NULL;

if (theAspect == NULL) theAspect = new MyAspect();

return theAspect;

}

};

Page 32: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Summary

• AspectC++ facilitates AOP with C++– AspectJ like syntax and semantics

• Full obliviousness and quantification– aspect code is given by advice– joinpoints are given declaratively by pointcuts– Implementation of crosscutting concerns is fully encapsulated in

aspects

• Good support for reusable and generic aspect code– aspect inheritance and virtual pointcuts– joinpoint API

Page 33: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Tool Support

• ac++ compiler– open source and the base of other tools

• AspectC++ add-in for MS Visual Studio– commercial product

• AspectC++ plugin for Eclipse (ACDT)– open source

Page 34: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

About ac++

• www.aspect.org (Linux, Win32, Solaris, source, docs, etc.)

• Transforms AspectC++ to C++ code– machine code is created by the back-end (cross-)compiler– supports g++ and Visual C++ specific language extentions

• Current version 0.9 (<1.0)– no optimizations for compilation speed– no weaving in templates– but already more than a proof of concept

Page 35: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Aspect Transformations

• Aspects are transformed to ordinary C++ classes• One static aspect instance is created by default• Advice becomes a member function• “Generic advice” becomes a template member function

• A function call is replaced by a wrapper function• A local class with the wrapper function invokes the advice code for

the joinpoint

• The transformed code is built using C++ compiler

Page 36: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Pros and Cons

• AOP with pure C+++ no special tool required- requires in-depth understanding of C++ templates- the component code has to be aspect-aware- no pointcut concern, no match expressions

• AspectC+++ ac++ transforms AspectC++ into C++

+ various joinpoint types

+ support for advanced AOP concerns: cflow, joinpoint API

- longer compilation time

Page 37: AOP and Aspect C++ presentation by Igor Kotenkov based on presentation by Andreas Gal, Daniel Lohmann and Olaf Spinczyk.

Roadmap

• Parser– full support of templates. Will accept g++ and VC++ STLs

– better performance

• Advice for object access, for object instantiation• Weaving in macro-generated code• cflow with context variables• Dependancy handling


Recommended