• No results found

2.3 Aspect oriented programming for distributed applications

2.3.1 Domain specific languages

Lopes has proposed D [VL97], a framework of three languages to modularize concurrency and distribution issues in distributed applications. This AO framework used Java as the base language and two additional domain specific languages: COOL and RIDL. Using COOL pro- grammers define syntactical units called coordinators to handle concurrency (trough mutual exclusion specifications). RIDL provides syntactical units called portals to address problems of remote invocation and data passing between execution spaces. These two languages pro- vide an example of how, using separate languages for specific concerns, we can modularize crosscutting concerns. Note that this framework weaves three programs (a Java program, a COOL program, and a RIDL program) into one executable. We now present the main characteristics of each of the two domain-specific aspect languages.

COOL

COOL is a language that deals with mutual exclusion, synchronization state, guarded sus- pension, and notification. Using COOL, programmers write coordinators that are associated to instances of the classes they coordinate. A coordinator is defined as follows:

Coordinator ::=

[per class] coordinator ClassList CoordinatorBody

If the optional per class declaration is omitted coordinators are associated to one specific ob- ject by default. Such coordination is referred to as “coordination per object” and implies that there will be a coordinator instance for each object of the classes in the class list (non-terminal ClassList). On the other hand, if per class is used, one coordinator is associated to all the objects of the classes in ClassList. The coordinator’s (non-terminal CoordinatorBody) body may include condition variables, regular variables, self exclusive declarations on methods, declarations on mutually exclusive methods, and method managers (used to define guarded suspension and notifications of thread,i.e., used to define method coordination).

Figure 2.3 shows an example of a coordinator for the ConnectionPool class, a typi- cal component of information systems in distributed setting (e.g., a data base connection pool). The coordinator uses the default instantiation (per object). The first line in the body of the coordinator declares the methods getConnection and releaseConnection, from ConnectionPool, as self exclusive, i.e., in the same object neither putConnection nor takeConnection can be executed by more than one thread at a time (e.g., two threads cannot execute the getConnection method concurrently). Line 3 defines getConnection

1 oordinator ConnectionPool {

2 selfex getConnection, releaseConnection;

3 mutex {getConnection, releaseConnection};

4 condition empty = false, full = false;

5 getConnection: requires !empty;

6 on_exit {

7 if (full) full = false;

8 if (usedConnections == capacity) empty = true;

9 }

10 releaseConnection: requires !full;

11 on_exit {

12 if (empty) empty = false;

13 if (usedConnections == 0) full = true;

14 }

15 }

Figure 2.3: COOL coordinator example

Portal ::= portal ClassName ’{’PortalBody’}’

PortalBody ::= {RemoteMethodsDecl} [default: TransferableTypeList]

RemoteMethodsDecl ::= ReturnType MethodName(ParameterList) [’{’ ObjectTranferDecl ’}’]

ReturnType ::= JavaType | void

ObjectTransferDecl ::= ObjectId : Mode

ObjectId ::= Id | return

Mode ::= gref | copy [’{’{CopyDirective}’}’]

CopyDirective ::= ClassName SelectionPrimitive VariableList

SelectionPrimitive ::= only | bypass

VariableList ::= VariableName | all.TypeName

Figure 2.4: RIDL language (excerpts)

and releaseConnection as mutually exclusive, i.e., both methods cannot be executed con- currently in one object. In lines 5 to 9 the coordinator defines a method manager for the getConnection method. This method manager requires the pool to have at least one con- nection (!empty). Additionally, on the method exit the manager updates the condition variables depending of the values found in variables usedConnections and capacity from ConnectionPool. Note that full and empty are defined as condition variables in line 4, they can thus be used for guarded suspension purposes. Finally, the coordinator defines a method manager for method releaseConnection in lines 10 to 14.

RIDL

RIDL is a domains specific aspect language for remote interfaces used to encapsulate code re- lated to remote invocation and data transfer between different execution spaces. The grammar shown in figure 2.4 shows the essentials of the RIDL language. A RIDL program is composed of a set of portals. Portals are syntactic units defining remote methods, parameter passing,

1 portal BankSystem {

2 boolean fundTransfer(Account originAccount, Account account, Value value) {

3 //Only strings are copied.

4 originAccount: opy {Account only all.String;}

5 account: opy {Account only all.String;}

6 value: opy {Value;}

7 };

8 Value withdraw(Account account, Value value){

9 //for return object, exclude this edge; this excludes the copies

10 // and breaks nasty cycle. 11 return: opy

12 account: opy {Account only id}

13 value: opy

14 };

15 Value credit(Account account, Value value) { 16 //for return object copy the return value

17 return: opy

18 // for Account, bypass the amount

19 account: opy {Account bypass amount;}

20 }; 21 }

Figure 2.5: RIDL portal example

and distributed behavior of objects. A portal is declared using the terminal portal, an exist- ing java class name, and a portal body. A unique portal instance is associated to each instance of the defining class. The portal body may contain declarations of remote methods, and a default rule for parameter passing in remote calls (see non-terminal RemoteMethodsDecl ). Such remote method declarations define a subset of the publicly available methods of the defining class. The methods declared in the body will represent the remote interface of the respective object. Besides the method signature (i.e., return type, method name, and param- eters), the remote declaration may be extended with a set of explicit rules defining parameter passing modes for the remote method declaration. Those rules can predicate over method return values and parameters. Concretely, programmers may decide that objects are to be passed by reference (see terminal gref) or by copy (terminal copy). Additionally, the copy directive allows programmers to control how the object graph with the respective object as root is serialized and transfered. In particular, programmers can state which fields in the respective object are copied, using the only directive, or which fields should not be copied, using bypass.

Figure 2.5 shows an example of a RIDL portal for a bank system. The example header defines the portal for objects of type BankSystem (see line 1). The body declares as remote three different methods from BankSystem class: fundTransfer, withdraw, and credit. Each declaration is modified by data passing directives. For example, in the first remote method declaration the statement in line 4 states that only the fields of type string from objects of type Account will be included, when copying the parameter originAccount. Similarly, the definition as a remote method of withdraw (lines 8 to 13) states that the copies of objects of type Account only contain a copy of the id field (see line 12) in the copied object graph having as root parameter account. Finally, in the declaration of method credit the field amount from classes Account is bypassed, i.e., not serialized (see line 20) when the account

value is copied. Classification

Table 2.8 shows the classification of the D framework according to the taxonomy presented in section 2.1. From the table one of the differentiating features of this approach is the object graph query language that is used to have a fine grained access to the passing by copy behavior. Additionally the language proposes remote method calls as distribution mechanism, mutual exclusion for concurrency, and synchronous communication between processes. The pointcut language is restricted to atomic methods executions. Finally, the framework proposes static deployment, per class and per object instantiation, static weaving, and limited means for composition.