<
aspect xmlns:cpp="
http://www.sdml.info/srcML/cpp"
xmlns:xsi="
http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
xmlns="
http://control.ee.ethz.ch/XWeaver/AspectX"
xmlns:src="
http://www.sdml.info/srcML/src"
xsi:schemaLocation="
http://control.ee.ethz.ch/XWeaver/AspectX ../../../../src/xsd/aspectX.xsd"
name="
CarSynchronizeWindows">
<
description>
Sample aspect program for "car example" that show how to add synchronization code
(for MS Windows) to existing code.
In this sample, the following is inserted:
<
ol>
<
li>
code to the constuctor that initializes a mutex (creates the constructor if it doesn't exist);
<
i>
mutex</
i>
is a variable that has a <
i>
mut</
i>
ual <
i>
ex</
i>
clusive access and is used as a <
i>
lock</
i></
li>
<
li>
code that locks the mutex at the beginning of the synchronized function</
li>
<
li>
mutex variable to the class that is to be synchronized.</
li><!---->
<
li>
preprocesor directives <
code>
#include <windows.h></
code>
and <
code>
#include "MutexWrapper.h"</
code></
li>
</
ol>
It also uses the class <
code>
MutexWrapper</
code>
distributed together with other classes of car example.
In order to test the aspect, check the <
code>
main()</
code>
function in the
sample C++ code and uncommment three lines labled as to be commented out
(lines 42 to 44 in <
code>
main.cpp</
code>
).
<
author>
I. Birrer, O. Rohlik</
author>
<
see>
CarBeginEnd</
see>
<
see>
CarPostCondition</
see>
<
see>
CarPreCondition</
see>
<
see>
Synchronization</
see>
</
description>
<
pointcut type="
src:class"
name="
syncClasses"
constraint="
src:name='PetrolStation'">
<
description>
Points to all classes which have to be synchronized. In this sample
aspect, only one class will be synchronized: <
code>
PetrolStation</
code>
. </
description>
</
pointcut>
<
pointcut type="
src:unit"
name="
syncClassesDef">
<
description>
Points to units (files) which contain the definitions of the methods
to be synchronized.</
description>
<
restriction type="
isDefinitionOf">
<
pointcutRef ref="
syncClasses"
type="
src:class" />
</
restriction>
</
pointcut>
<
pointcut name="
syncClassesConstrDef"
type="
src:constructor">
<
description>
Points to definition of a constructor of the class that contains methods
to be synchronized.</
description>
<
restriction type="
within">
<
pointcutRef ref="
syncClassesDef"
type="
src:unit" />
</
restriction>
</
pointcut>
<
pointcut name="
syncClassesConstrDecl"
type="
src:constructor_decl">
<
description>
Points to declaration of a constructor of the class to be synchronized.</
description>
<
restriction type="
within">
<
pointcutRef ref="
syncClasses"
type="
src:class" />
</
restriction>
</
pointcut>
<
pointcut type="
src:function"
name="
lockedFunctions">
<
description>
Points to all functions in the class to be synchronized.</
description>
<
restriction type="
within">
<
pointcutRef ref="
syncClassesDef"
type="
src:unit" />
</
restriction>
</
pointcut>
<
advice name="
addConstrDecl"
type="
add">
<
description>
Adds construtor declaration to classes which are to be sychronized and do not have a constructor.</
description>
<
pointcut type="
src:class">
<
and>
<
not>
<
restriction type="
contain">
<
pointcut type="
src:constructor_decl" />
</
restriction>
</
not>
<
pointcutRef ref="
syncClasses"
type="
src:class" />
</
and>
</
pointcut>
<
codeModifier type="
declaration">
<
accessModifier type="
public" />
<
text>
${className}();</
text>
</
codeModifier>
</
advice>
<
advice name="
addConstrDef"
type="
add">
<
description>
Adds construtor definition if the constructor was not defined.
It contains a piece of code that initializes the lock (mutex) variable.</
description>
<
pointcut type="
src:unit">
<
and>
<
restriction type="
isDefinitionOf">
<
pointcutRef ref="
syncClasses"
type="
src:class" />
</
restriction>
<
not>
<
restriction type="
contain">
<
pointcut type="
src:constructor" />
</
restriction>
</
not>
</
and>
</
pointcut>
<
codeModifier type="
definition">
<
text>
${className}::${className}() {
cout << "Initialize mutex... " << endl;
// Create a mutex with no name. Do not obtain ownership of it.
shared_mutex = CreateMutex( NULL, FALSE, NULL );
if (shared_mutex == NULL) {
cerr << "Mutex initialization failed" << endl;
exit(EXIT_FAILURE);
}
}</
text>
</
codeModifier>
</
advice>
<
advice type="
begin"
name="
beginLockFunction">
<
description>
Locks the mutex at the beginning of each method in each class to be synchronized.</
description>
<!---->
<
pointcutRef ref="
lockedFunctions"
type="
src:function" />
<
codeModifier type="
codeFragment">
<
text>
MutexWrapper mutexWrapper( &shared_mutex );</
text>
</
codeModifier>
</
advice>
<
advice type="
add"
name="
addFields">
<
description>
Adds field variable <
code>
shared_mutex</
code>
that is used as a lock
to each class to be synchronized. The field variable is of type <
code>
HANDLE</
code>
.</
description>
<
pointcutRef ref="
syncClasses"
type="
src:class" />
<
codeModifier type="
declaration">
<
accessModifier type="
private" />
<
text>
/**
* Mutex for the synchronization of methods.
* Added by aspect 'synchronizeWindows.xml'
*/
HANDLE shared_mutex;</
text>
</
codeModifier>
</
advice>
<
advice type="
add"
name="
addIncludesToDeclaration">
<
description>
Adds appropriate header files to each file that contains classes to be synchronized. The inserted
preprocesor directives are: <
code>
#include <windows.h></
code>
and
<
code>
#include "MutexWrapper.h"</
code>
.</
description>
<
pointcut type="
src:unit">
<
restriction type="
contain">
<
pointcutRef ref="
syncClasses"
type="
src:class" />
</
restriction>
</
pointcut>
<
codeModifier type="
include">
<
text>
#include <windows.h></
text>
<
text>
#include "MutexWrapper.h"</
text>
</
codeModifier>
</
advice>
<
advice type="
add"
name="
addIncludesToDefinition">
<
description>
Adds appropriate header files to each definition file that contains definitions of methods
of classes to be synchronized. The inserted preprocesor directives are:
<
code>
#include <windows.h></
code>
and
<
code>
#include "MutexWrapper.h"</
code>
.</
description>
<
pointcutRef ref="
syncClassesDef"
type="
src:unit" />
<
codeModifier type="
include">
<
text>
#include <windows.h></
text>
<
text>
#include "MutexWrapper.h"</
text>
</
codeModifier>
</
advice>
<
advice type="
begin"
name="
initializeMutex">
<
description>
Inserts a piece of code that initializes the lock. It is inserted to the constuctor
of class to be synchronized (if the constructor exists).</
description>
<
pointcutRef ref="
syncClassesConstrDef"
type="
src:constructor" />
<
codeModifier type="
codeFragment">
<
text>
cout << "Initialize mutex... " << endl;
// Create a mutex with no name. Do not obtain ownership of it.
shared_mutex = CreateMutex( NULL, FALSE, NULL );
if (shared_mutex == NULL) {
cerr << "Mutex initialization failed" << endl;
exit(EXIT_FAILURE);
}</
text>
</
codeModifier>
</
advice>
</
aspect>
v