Document not found! Please try again

A Concurrent Object-based Model and its Use for Coordinating Java

0 downloads 0 Views 215KB Size Report
how our model can be used to coordinate Java events owing on a software bus. .... We adopt this solution to avoid the violation of the encapsulation principle. ..... 9th International Conference on Parallel and Distributed Computing Systems, ...
A Concurrent Object-based Model and its Use for Coordinating Java Components S. Majoul, C. Percebois, J.-P. Bodeveix IRIT, Universite Paul Sabatier, 118 route de Narbonne 31062 Toulouse Cedex 4 - France e-mail: fmajoul,perceboi,[email protected]

Abstract We present a canonic model expressing the behavior of a system of communicating objects through multiset rewriting. Then, we discuss the integration of the so-de ned model into the Java language. The choices and the restrictions made to implement the model as well as the architecture of the system are presented. Finally, we propose to use the prototype that we carried out as a coordination tool for communicating Java components. We focus on applications built around InfoBus, a standard package providing an event-based protocol for dynamic data-sharing between components. We show how our model can be used to coordinate Java events owing on a software bus.

1: Introduction The need of coordinating distributed activities has involved the design of coordination models. Some languages introduce the concept of shared dataspace as main tool for coordination. They o er a set of basic associative operations on a unique shared database called tuple space. Linda [9], one of the rst advocates of this programming style, de nes mainly an interface between a high level language and a database. Several models such as PoliS [5] improve on Linda by introducing multiple shared dataspaces and a more precise interaction protocol relying on the chemical metaphore [2]. On the other hand, the increased popularity of object-oriented programming has lead to the emergence of Linda-like object models such as [10] and [11] where tuples are rst class objects. Another family of models relies on a rule-based mechanism integrating both concurrency and object aspects. We can put forward the Maude language [13] which uses a rewriting logic and the COOLL language [4] that relies on a fragment of linear logic. However, the handling of some object aspects in Maude are purely syntactic, notably regarding inheritance. Furthermore, the approach adopted in COOLL is constrained by the underlying logic, which obscures the expression of some features, for example process joining. Our proposal, presented in section 2, consists in a general framework incorporating multiple data spaces management and parallelism. It relies on an algebraic representation of an object database whose transformations are expressed by rewriting rules. Unlike Maude, inheritance is implicit and is made possible by introducing a partial-order relation on rule heads that reduces the non-determinism by selecting the most speci c rules. In section 3, an implementation of the model in the Java language is studied. Then, we propose in section 4 to coordinate Java events on a software bus. Finally, we conclude in section 5 and discuss some directions for future work.

2: The calculus model 2.1: Objects An object is seen as a multiset of valued attributes called the object context or the object state. The domain of an attribute is a term of the Herbrand universe. The attributes are separated by the operator  supposed associative, commutative and with neutral element . A special eld called self is introduced to designate an object. For example a point p of coordinates 1 and 4 is represented as follows: self(p)  x(1)  y(4). An object database is represented by a sequence of ground terms denoting the objects which are connected by the associative-commutative operator # having # as neutral element. In the following, we consider the operator  as having a higher precedence than #. A database containing, for example, three points p1 (1; 2), p2(4; 6) and p3(5; 3) is coded by the term: self(p1)  x(1)  y(2) # self(p2 )  x(4)  y(6) # self(p3)  x(5)  y(3)

2.2: Rewriting rules Object evolution is speci ed by rewriting rules modulo the associativity and the commutativity of the operators  and # [3]. These rules apply to terms representing an object database and code state transitions of the database. An execution is a succession of rule applications deducing an irreducible term from the initial one. The syntax of a rewriting rule is the following:

s11  : : :  s1 1 # : : : # s1  : : :  s p ,! t11  : : :  t1 1 # : : : # t1  : : :  t n

|

{z l

p

n p

n0

}

|

{z

q

n0q q

}

r

where the s and the t are rst order terms. The rule l ! r applies to a term t if there exists a subterm u of t, a term u0 equivalent to u (modulo the associativity and the commutativity of the operators  and #), and a substitution  such that u0 = l . So, the application of the rule rewrites the term t into t[r=u] where u is the term matched by l, called pattern, and the term tnu is called the remaining context. Note that rewriting must be atomic in order to ensure the coherence of the object database. Furthermore, the model is essentially non-deterministic. j i

j i

2.3: Rule classi cation In order to reduce the non-determinism inherent in the model, we introduce a partial-order relation on rule heads which restricts the selection to the most speci c ones. A rule r1 is more speci c than a rule r2 if and only if terms reducible by r1 are also reducible by r2 . Among the most speci c rules applicable to a term, one is selected non-deterministically and is applied to the term. We have presented in [12] a formal de nition of rule speci city as well as a classi cation algorithm.

2.4: Message sending This model supports message sending naturally since a rule may directly insert a term into the context of another object. For reasons of convenience, we de ne the operator o : m similar to asynchronous method invocation in object-oriented languages by: self(o)  x # o : m  y ,! self(o)  x  m # y Note that two messages sent to a same object are not necessarily handled in order of arrival.

2.5: Example We consider the dining philosophers problem as presented in [4]. The following rule speci es the behavior of a hungry philosopher p in the presence of two free forks f1 and f2 : self(p)  hungry # self(f1 )  free # self(f2)  free ! self(p)  eat(f1 ; f2) # self(f1) # self(f2 ) When the rule applies, the context of each matched object is consumed an a new one is produced where the philosopher is eating and the forks are no longer free. After eating, the philosopher puts the forks down and thinks. This behavior is expressed by the following rule: self(p)  eat(f1 ; f2) ,! self(p)  think  f1 : free  f2 : free that consumes the message eat(f1 ; f2) from the context of the philosopher p and produces the message think. The forks f1 and f2 become free by sending the message free to each of them.

3: Use of the model for coordinating Java objects Many researches have been made to coordinate message sending among objects. Most of them introduce a meta-level interception mechanism between senders and receivers. One approach consists in matching messages one by one and redistributing them to the receiver when some condition is ful lled [1]. However, in this proposal, reaction to a set of messages must be implemented in terms of reaction to a single message. Another approach, suggested by Frolund and Agha in [8], introduces the notion of activator that speci es the ring of an action when a set of messages is present. In the following sections, we show how our model can be used as a multi-object coordination tool based on the second approach. Our model can be implemented in at least two ways: either as a real programming language or as a tool that can be integrated into an existing programming language. We adopt the second approach because most of the existing programming languages do not provide mecanisms dealing with multi-object coordination. Furthermore, it is easier for a programmer to use tools than to learn a new programming language. The increasing development of concurrent and distributed applications in the Java language has motivated us to implement our model in this language.

3.1: Integration into the Java language The Java platform contains a large collection of ready-made software components (Java API) grouped into libraries or packages. The prototype that we carried out is provided as a Java package so that programmers can use it like any Java library. Nevertheless, the integration of the model into the Java language was not direct because the former is designed while disregarding any programming language. Hence, some restrictions and choices have to be made in order to comply with the objectoriented principles on which the Java language relies.

3.1.1: Problems raised by the integration In the proposed model, a left hand of a rule mentions the attributes and messages that should be present in an object context. Exhibiting the state of an object in such a way violates the encapsulation principle of object-oriented programming. Furthermore, the model allows to express the mutation of an object through the production/consumption mechanism, which is incompatible with strong typing in Java. Hence, expressing object mutation in terms of change of membership class might be expensive.

3.1.2: Adopted solutions The JavaBeans library, de ning a software component model for Java, proposes an elegant solution to access private properties of a bean in order to be customized. A bean property can be either a simple data eld or a computed value. It can be accessed through setter and getter methods whose names follow speci c rules called design patterns. For example, the setter and getter methods of a property foo are respectively: public void setFoo(PropertyType value); public PropertyType getFoo(); We adopt this solution to avoid the violation of the encapsulation principle. So, a rewriting rule may have access to an object property by invoking the corresponding getter method. The property may be updated either through its setter method or through any other method of the object. We remedy the problem of object mutation by forbidding the production and consumption of object attributes. However, to bene t from the expressiveness of the production/consumption mechanism on which the model relies, we introduce another data type called message di erent from an object method. Messages are atoms which can be added to and removed from the context of an object matched by a rewriting rule. Such messages are only managed by the rules and are not accessible by the Java code of an application. Hence, objects handled by a rule contain a static set of attributes accessible through method invocation and a dynamic multiset of messages. A left hand of a rule enumerates the set of attributes and the multiset of messages that must be present in the context of the matched objects. As for the right hand, it contains any Java code. The application of a rule removes all the matched messages of the current objects and executes the Java code given in the right side.

3.2: Architecture The model is implemented as a Java package called jrules that can be used in a Java application. The RuleManager interface, implemented by the RuleGateway class, speci es the methods allowing a Java programmer to use an already-compiled rule base. public interface RuleManager f public void register (Object ob, boolean persist); public void unregister (Object ob); public void activate (RuleBase rb, int mode); public void desactivate ();

//registration of an object //activation of the rule engine

g//end RuleManager

An instance of the RuleGateway class de nes a gateway to a rule base. It contains at least a rule base, two object bases, one for persistent objects and the other for non-persistent objects and a rule engine undertaking pattern-matching, rule selection and rule application.

3.3: Rewriting Java objects Rules are grouped into a named rule base. Messages exchanged between objects are declared globally by specifying their signature. Each rule is named and consists in a declaration part, a pattern part and an action part. The action part contains Java code extented with the operators : (message sending), NEW (creation of non-persistent objects) and NEWP (creation of persistent objects). For example, the behavior of a hungry philosopher, speci ed in x2.5, is de ned by the rule:

rulebase Dinner f message free(); rule tryToEat f var Philosopher p;

Fork f1, f2; self(p), hungry(b) & f: b == true :g # self(f1), free() # self(f2), free() => f: p.eat(f1,f2); f1:free(); f2:free();

g

g

p.think() :g

This rule involves three objects: a philosopher and two forks speci ed by three occurrences of the keyword self. A philosopher is matched by the variable p if the value b of its eld hungry is true. The two forks are matched by the variables f1 and f2 if their respective message boxes contain the message free. When the rule applies, a message free is retrieved from the message box of each fork and the method eat is invoked on p. When the philosopher ends its meal, he releases the forks by sending a message free to each fork and starts thinking.

3.4: Implementation The prototype that we carried out comprises two parts. One part deals with rule compilation and code generation. The other one implements pattern-matching, rule selection and rule application.

3.4.1: Rule compilation The compilation of a rule le generates new classes: for the rule set, for each rule and for each message declaration. Then, the newly generated classes are compiled via the Java compiler. The jrules package contains the Message, RuleBase and Rule classes which constitute the super-classes for the generated ones. The patterns de ned in a rule base are compiled into a Rete net [7] allowing to perform associative-commutative pattern matching. The Rule class has two abstract methods verify and execute. In the sub-classes of Rule, the rst method contains the generated code for the conditions of the current rule while the second one contains the generated code for the action part of the rule. The Rete net generated at compile time contains four kinds of nodes. A token owing on the net maintains a reference to an object to be matched and the current rule's free variables called environment. The left side of a rule dealing with n patterns (objects) is compiled into a net with n EntryNodes checking the type of the matched object, n sequences of AlphaNodes, each starting with an EntryNode, n , 1 BetaNodes and an ExitNode storing successful tokens. A BetaNode joins the AlphaNodes ending two sequences. An AlphaNode, associated to an object's eld or message, tries to unify the environment carried by the token with the eld or the message arguments and checks the eventual conditions by invoking verify method on the corresponding rule.

3.4.2: Rule activation Rule activation is ensured by a RuleEngine object that encapsulates a control thread. Its task consists in performing pattern matching, selecting a rule from the obtained con ict set and applying the selected rule. Pattern-matching is achieved by an implementation of a variant of the Rete algorithm [7] that undertakes backtrack with consumption. A token enters the net through an EntryNode and tries to reach an ExitNode. While the token is progressing on the net, the free variables that it carries are instanciated gradually. In this implementation, each token on the net encapsulates a control thread

hence allowing to perform pattern matching concurrently. Granularity of the matching system is managed by a controller object which can be customized according to the machine on which the system runs. Pattern-matching terminates when all the control threads encapsulated by the tokens terminate. The set of pairs composed by a rule and its corresponding successful tokens, which are stored in the rule's ExitNode, forms the con ict set. In the current version of the prototype, the classi cation algorithm given in [12] is not implemented yet. Priority is awarded to rules according to their declaration order. Among the set of successful tokens obtained from the most speci c rule's ExitNode, one token is non-deterministically selected. Then, this rule is applied by invoking its execute method with the instanciated environment in parameter. Finally, non-persistent objects that are matched by the applied rule are removed from the non-persistent object base.

4: Application We focus on applications using a software bus as a communication support and requiring multiobject coordination. For this purpose, we use InfoBus1 [6], a public speci cation of dynamic datasharing technology which enables Java developpers to equip their components to communicate with other components in a structured way. Components in an InfoBus application can be classi ed in three types: data producers, data consumers and data controllers. An individual component can act at once as a producer, a consumer and also a controller. Data ows between components in named objects known as data items. Data controllers are specialized components that mediate the rendezvous between producers and consumers.

4.1: The InfoBus protocol for data exchange InfoBus components use an event-based mechanism to announce data availability and request data among other components on the bus. Data exchange is made by name, thereby, components connected to a bus may exchange data without knowing about each other. A data producer listens for requests and announces data availability or revocation by ring an event of type InfoBusItemAvailableEvent or InfoBusItemRevokedEvent. A consumer listens for availability and revocation events, and requests data by ring an InfoBusItemRequestedEvent. The role of a data controller is to play trac cop on the bus. It participates in the distribution of events to consumers and producers. The default data controller performs one-to-all communication. A data consumer (respectively producer) has to implement the interface InfoBusDataConsumer (respectively InfoBusDataProducer) provided by the infobus package. The InfoBusDataConsumer interface speci es two methods: public void dataItemAvailable (InfoBusItemAvailableEvent event); public void dataItemRevoked (InfoBusItemRevokedEvent event); These methods are called by an InfoBus instance on which data exchange occurs in order to notify the consumer about the availability of some data in the rst case, and the revocation of an announced data in the second one. The interface implemented by a producer supplies a method: public void dataItemRequested (InfoBusItemRequestedEvent event); which is also called by the bus in order to inform the producers about a request for a data. 1

InfoBus is jointly designed by Lotus Development Corporation and Sun Microsystems'JavaSoft Division.

An InfoBus participant de nes its reaction to a received event by implementing the method(s) speci ed by the appropriate interface(s). Note that all these methods de ne the reaction to a single event. The infobus package provides classes and methods de ning operations allowing to get information about an event such as its source, the name of the announced data and the data.

4.2: Event coordination Some applications involve object reactions whose logical cause is a set of events rather than a single event. Nevertheless, the infobus package provides classes and interfaces allowing to implement the reactions of an InfoBus participant caused by the reception of exactly one event. So, programmers must implement reaction to a set of events in terms of reaction to a single event. In order to defer a reaction until a number of events have been received, components must maintain a number of temporary variables which re ect the events received so far. Hence, programmers are forced to intermix two orthogonal design concerns: when to react and how to react [8]. The coordination of an event set received by an InfoBus participant (producer/consumer) can be expressed via a set of rewriting rules. The InfoBus participant has to implement the RuleManager interface supplied by the jrules package using the implementation provided by the RuleGateway class. Its reaction to an event reception consists in registering the event as a non-persistent object so that it can be handled by the rules once. Similarily, the redistribution of events received by a data controller to InfoBus participants can be expressed by a set of rewriting rules.

4.2.1: Example: the dining philosophers problem

We can imagine the following scenarios for the dining philosophers problem. In this example, we are interested in the coordination aspect rather than the resource management aspect.

The arrival A restaurant waiter manages a set of tables. When a group of philosophers arrives,

the waiter announces the arrival to all the tables of the restaurant. In response, each table informs the waiter about its state: FREE or BUSY. The waiter waits for the replies and accepts the group if at least one table is free. In this scenario, the waiter acts both as a producer and a consumer while the table acts as a producer. The waiter is noti ed by the arrival of a philosopher group through the call performArrival. This method is de ned in the class Waiter below. The bus res on behalf of the waiter an InfoBusItemAvailableEvent carrying the name ARRIVAL when the waiter invokes the method fireItemAvailable on the current bus. This method, provided by the InfoBus class has three arguments: the rst one is the name to be announced, the second one is an optionnal description of the data and the last one is the event's source. A reference to the current bus is obtained through the getter method getInfoBus of the interface InfoBusMember supplied by the infobus package. public class Waiter implements InfoBusDataProducer, InfoBusDataConsumer, RuleManager,... f private RuleGateway gateway; private Group group; ... public void performArrival (Group g) f group = g; getInfoBus().fireItemAvailable("ARRIVAL",null,this); g

public void

dataItemAvailable (InfoBusDataItemAvailableEvent e)

f gateway.register(e,false); g

public Group getGroup () g

f return group; g

//the getter method of the property group //invoked during pattern-matching

When a table receives an event announcing the availability of a data named ARRIVAL, the bus res on behalf of the table an InfoBusItemAvailableEvent, carrying the name FREE or BUSY according to the table state stored in the attribute isFree. This reaction is de ned by the method dataItemAvailable of the class Table below. public class Table implements InfoBusDataProducer,... f private boolean isFree; ... public void dataItemAvailable (InfoBusDataItemAvailableEvent e) f if (e.getDataItemName().equals("ARRIVAL")) if (isFree) getInfoBus().fireItemAvailable("FREE",null,this); else getInfoBus().fireItemAvailable("BUSY",null,this); g

g

The reception of all the replies by the waiter can be coordinated according to the rules below. We suppose that the restaurant contains only two tables. The reaction of the waiter to an InfoBus event consists merely in registering the event to a RuleGateway instance referenced by the attribute gateway of the class Waiter. The Acceptance rule applies when at least one event announces the availability of a free table. In this case, the announced table is returned by the method requestDataItem provided by the InfobusItemAvailableEvent class. The table becomes occupied by the philosophers (method setGroup) which sit down round it (method sitDownRound). If all the received events carry the name BUSY, the Refusal rule applies and the philosopher group is refused by invoking the method noPlaceLeft supposed de ned in the class Group. rule

Acceptance InfoBusItemAvailableEvent e1,e2; String n1,n2; Waiter w; Group g; self(w), group (g) # self(e1), dataItemName(n1) & f: n1.equals("FREE") :g # self(e2), dataItemName(n2) & f: n2.equals("FREE") || n2.equals("BUSY") :g => f: Table t = (Table) e1.requestDataItem(w,null); t.setGroup(g); g.sitDownRound(t); :g g//end Acceptance

f

rule

var

Refusal InfoBusItemAvailableEvent e1,e2; String n1,n2; Waiter w; Group g; self(w), group(g) # self(e1), dataItemName(n1) & f: n1.equals("BUSY") :g # self(e2), dataItemName(n2) & f: n2.equals("BUSY") :g => f: g.noPlaceLeft(); :g g//end Refusal

f

var

Figure 1 shows the interaction between the actors participating in this scenario during the negociation phase. Zigzag arrows depict event ring while the others represent method invocation. The numbers on the arrows indicate the order in which the methods are invoked.

Around the table Around the table, the actors are the forks on the table, the philosophers and

the table itself. A fork acts as a producer that announces its availability when it becomes free. A philosopher acts both as a producer notifying that he is hungry and as a consumer that picks up forks. Finally, the table acts both as a data controller that mediates the rendezvous between a hungry philosopher and two free forks, and as a data producer that provides the forks to the

register(event3..) (5)

performArrival() (1)

group

gateway (6) register(event4..)

waiter

event3 event4

fireItemAvailable("ARRIVAL"..) (2)

InfoBus fireItemAvailable("FREE"..) (3)

fireItemAvailable("FREE"..) (4)

event1 event2

table1

table2

Figure 1. The arrival

philosopher. The Rendezvous rule, given below, res when three events meet: one announces the availability of a hungry philosopher and the others announce the availability of two free forks. rule Rendezvous f var InfoBusItemAvailableEvent e1,e2,e; String n,n1,n2; Table t;

self(t) # self(e), dataItemName(n) & f: n.equals("HUNGRY") :g # self(e1), dataItemName(n1) & f: n1.equals("FORK") :g # self(e2), dataItemName(n2) & f: n2.equals("FORK") :g => f: TwoForks tf = new TwoForks((Fork) e1.requestDataItem(t,null), (Fork) e2.requestDataItem(t,null)); Philosopher p = (Philosopher) e.getSourceAsProducer(); t.reserveTwoForksFor(tf,p); t.getInfoBus().fireItemAvailable("TWO_FORKS",null,t,p); :g g//end Rendezvous

When the Rendezvous rule applies, an object tf of type TwoForks is created. It contains the fork announced by the event e1 and the one announced by the event e2. The table reserves these forks to the hungry philosopher p which is the source of the event e. The method getSourceAsProducer, de ned in the InfoBusItemAvailableEvent class, returns the source of the current event. The method reserveTwoForksFor, supposed de ned in the Table class, associates two forks tf to a philosopher p so that they can be returned to the philosopher when he requests them. Finally, the table requests the bus to directly notify the philosopher p about the availability of two forks. The last parameter of fireItemAvailable represents the consumer that receives the noti cation event. public class Philosopher implements InfoBusDataProducer, InfoBusDataConsumer,... f ... public void dataItemAvailable (InfoBusDataItemAvailableEvent e) f if (e.getDataItemName().equals("TWO_FORKS")) f TwoForks tf = (TwoForks) e.requestDataItem(this,null);

g

g

g

eat(tf);

releaseForks(tf);

think();

leaveTheRestaurant();

On the reception of an available event carrying the name TWO FORKS, the philosopher gets the two forks reserved by the table, eats, releases the forks, thinks and leaves the restaurant. When a fork becomes free, an InfoBusItemAvailableEvent carrying the name FORK is red on behalf of the fork.

5: Conclusion We have presented a calculus model for a system of communicating objects. This model relies on a term algebra provided with the associative-commutative operators  and # used respectively as attribute and object separators. The evolution of an object of the database is speci ed by a set of rewriting rules. The non-determinism inherent in this kind of model is reduced by introducing a partial-order relation on rule heads restricting the selection to the most speci c rules. The increasing development of concurrent and distributed applications in the Java programming language has motivated us to implement our model in this language. The integration of the model into Java has raised some problems since the model was initially designed while disregarding any programming language. These problems are overcame by making some choices and restrictions. Finally, we have presented the InfoBus protocol for data exchange which relies on an event-based mechanism. We showed how our model can be used to coordinate events on a software bus. There are at least three directions for future work. One would be to implement the rule classi cation algorithm based on the partial-order relation over patterns. The second one would be to structure rule bases. Finally, it remains to experiment our prototype with distributed applications.

References [1] M. Aksit, K. Wakita, J. Bosch, L. Bergmans, and A. Yonezawa. Abstracting Object Interactions Using Composition Filters. In R. Guerraoui, O. Nierstrasz, and M. Riveill, editors, in object-based distributed processing, LNCS, pages 152{184. Springer-Verlag, 1993. [2] G. Berry and G. Boudol. The Chemical Abstract Machine. In Sevententh Annual ACM Symposium on Principles of Programming Languages, pages 81{94, San Francisco, CA., January 1990. [3] J.-P. Bodeveix, C. Percebois, and S. Majoul. An Object-Oriented Coordination Model based on Multiset Rewriting. In 9th International Conference on Parallel and Distributed Computing Systems, PDCS'96, Dijon, September 1996. [4] S. Castellani and P. Ciancarini. Exploring the Coordination Space with LO. Technical Report 94-6, UBLCS, University of Bologna, Laboratory for Computer Science, April 1994. [5] P. Ciancarini and M. Gaspari. Parallel Symbolic Computing with the Shared Dataspace Coordination Model. Technical Report 94-17, UBLCS, University of Bologna, Laboratory for Computer Science, July 1994. [6] M. Colan. InfoBus 1.1.1 Speci cation. http://java.sun.com/beans/infobus/, September 1998. [7] C. Forgy. Rete: A Fast Algorithm for the Many Patterns Many Objects Match Problem. Arti cial Intelligence, 19(1), September 1982. [8] S. Frolund and G. Agha. Abstracting Interactions Based on Message Sets. In P. Ciancarini, O. Nierstrasz, and A. Yonezawa, editors, in Object-Based Models and Languages for Concurrent Systems, LNCS. Springer-Verlag, 1995. [9] D. Gelernter. Generative Communication in Linda. ACM Transactions on Programming Languages and Systems, 7(1):80{ 112, 1985. [10] Keld K. Jensen. Toward a Multiple Tuple Space Model. PhD thesis, Aalborg University, Dept. of Mathematics and Computer Science, Inst. for Electronic Systems, 1994. [11] T. Kielmann. Designing a Coordination Model for Open Systems. In O. Nierstrasz, editor, Coordination Languages and Models, LNCS, pages 267{284. Springer-Verlag, 1996. [12] S. Majoul, C. Percebois, and J.-P. Bodeveix. Reasoning about Negative Conditions in a Concurrent Rewriting System. In 2nd France-Japan Workshop on Object-Based Parallel and Distributed Computation, Toulouse, October 1997. [13] J. Meseguer. A Logical Theory of Concurrent Objects and Its Realization in the Maude Language. In G. Agha, P. Wegner, and A. Yonezawa, editors, Research Directions in Concurrent Object-Oriented Programming. MIT Press, 1993.

Suggest Documents