10
Concurrency in Cooperative Objects C. S ibertin-B lanc IRIT, UniversitC Toulouse 1 Place A. France, F-3 1042 Toulouse Cedex E-mail: [email protected] Abstract CoOperative Objects (COOs) are a concurrent object-oriented modelling and programming language, which uses the Petri net theory to define the concurrency within each object, among objects, and also the inter-object asynchronous communication. SYROCO is a C+ -+ implementation of Cooperative Objects which proves to be efficient and convenient enough to support real size applications. The paper aims to show that intra-object concurrency is of paramount importance for models of object-oriented concurrency, and that intra-object concurrency is smartly supported by the integration of the object-oriented and Petri net paradigms. Namely, it discusses the model of concurrency adopted by COOS, and details how it is implemented in SYROCO. I. Introduction The object-oriented approach mainly relies upon the following attractive model: a (software) system is a collection of autonomous entities which cooperate in order to achieve the goals of the whole system. For a long time, this model has been supported by sequential languages which do not allow objets to run concurrently their activities. In such a case, the control of the system is centralised and the objets can not have a real autonomy. Up to date, there exist reliable operating systems or middlewares featuring high-level mechanisms for dealing with concurrency (e. g. threads) and distribution (e. g. CORBA for the communication between distant objets). The availability of such mechanisms eases the implementation of Concurrent object-oriented Languages (COOL) which effectively support the above mentioned model. All COOLs support inter-object concurrency, that is objets of a system may concurrently execute their own activity, while intra-object concurrency seems to be often neglected by standard models and languages of object- oriented programming. We claim that intra-object concurrency, that is the possibility for each object to have several concurrent activities, also is a very valuable feature which must be supported by COOLs. To argue this position, we shall show that the relevance of intra-object concurrency is a consequence of the inter-object concurrency and of the communication between objets. 1.1 communication protocols Within concurrent environments, two communication protocols are usually considered: message sending and synchronous requestheply. The message sending protocol consists of two steps: i) an object sends a message to the target and then ii) the target object accepts the message as soon as it is This protocol is asynchronous and allows for a great deal of concurrency, but it does not fit well the semantics of objets’ communications. Indeed, most often an object sends a message to another one in order to ask for some data or to give some work to be done, and it needs to receive some result or acknowledgement as a result of the message sent; thus, the target object must also send a message that serves as a reply to the initial message. Using the message sending protocol, a lot of code is devoted to manage object communications: sending the reply by the target object, receiving the reply by the object which initiated the communication, and above all keeping trace of the messageheply relationship by both (In a concurrent environment, an object may be waiting for several replies, and have several replies to send). In fact, message sending is a low-level protocol, so that the code of objets’ methods is much more difficult to design. In addition, it may be difficult to distinguish between initial messages and reply messages, so that the use relationship between objets is not clear: this is an important drawback from a structural design point of view. In order to avoid these constraints, many COOLs also support the synchronous request/reply protocol, that consists of the following three steps: i) the client object sends a message to the target object ii) the server object accepts the message as soon as it is iii) the client object receives the reply, and resumes its This Remote Procedure Call protocol accounts for the fact that most object communications include both a request and a reply message, and thus it is a higher-level protocol. But it also suffers some drawbacks: some available continues to work, able to process it. and blocks, able to, processes it, and sends a reply, work. 35 0-8186-7882-8/97 $10.00 0 1997 IEEE

[IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

  • Upload
    c

  • View
    213

  • Download
    0

Embed Size (px)

Citation preview

Page 1: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

Concurrency in Cooperative Objects

C. S ibertin-B lanc IRIT, UniversitC Toulouse 1 Place A. France, F-3 1042 Toulouse Cedex E-mail: sibertin @irit.fr

Abstract CoOperative Objects (COOs) are a

concurrent object-oriented modelling and programming language, which uses the Petri net theory to define the concurrency within each object, among objects, and also the inter-object asynchronous communication. SYROCO is a C+ -+ implementation of Cooperative Objects which proves to be efficient and convenient enough to support real size applications.

The paper aims to show that intra-object concurrency is of paramount importance for models of object-oriented concurrency, and that intra-object concurrency is smartly supported by the integration of the object-oriented and Petri net paradigms. Namely, it discusses the model of concurrency adopted by COOS, and details how it is implemented in SYROCO.

I. Introduction The object-oriented approach mainly relies upon the

following attractive model: a (software) system is a collection of autonomous entities which cooperate in order to achieve the goals of the whole system. For a long time, this model has been supported by sequential languages which do not allow objets to run concurrently their activities. In such a case, the control of the system is centralised and the objets can not have a real autonomy. Up to date, there exist reliable operating systems or middlewares featuring high-level mechanisms for dealing with concurrency (e. g. threads) and distribution (e. g. CORBA for the communication between distant objets). The availability of such mechanisms eases the implementation of Concurrent object-oriented Languages (COOL) which effectively support the above mentioned model.

All COOLs support inter-object concurrency, that is objets of a system may concurrently execute their own activity, while intra-object concurrency seems to be often neglected by standard models and languages of object- oriented programming. We claim that intra-object concurrency, that is the possibility for each object to have several concurrent activities, also is a very valuable feature which must be supported by COOLs. To argue this

position, we shall show that the relevance of intra-object concurrency is a consequence of the inter-object concurrency and of the communication between objets.

1.1 communication protocols Within concurrent environments, two communication

protocols are usually considered: message sending and synchronous requestheply. The message sending protocol consists of two steps:

i) an object sends a message to the target and then

ii) the target object accepts the message as soon as it is

This protocol is asynchronous and allows for a great deal of concurrency, but it does not fit well the semantics of objets’ communications. Indeed, most often an object sends a message to another one in order to ask for some data or to give some work to be done, and it needs to receive some result or acknowledgement as a result of the message sent; thus, the target object must also send a message that serves as a reply to the initial message. Using the message sending protocol, a lot of code is devoted to manage object communications: sending the reply by the target object, receiving the reply by the object which initiated the communication, and above all keeping trace of the messageheply relationship by both (In a concurrent environment, an object may be waiting for several replies, and have several replies to send). In fact, message sending is a low-level protocol, so that the code of objets’ methods is much more difficult to design. In addition, it may be difficult to distinguish between initial messages and reply messages, so that the use relationship between objets is not clear: this is an important drawback from a structural design point of view.

In order to avoid these constraints, many COOLs also support the synchronous request/reply protocol, that consists of the following three steps:

i) the client object sends a message to the target object

ii) the server object accepts the message as soon as it is

iii) the client object receives the reply, and resumes its

This Remote Procedure Call protocol accounts for the fact that most object communications include both a request and a reply message, and thus it is a higher-level protocol. But it also suffers some drawbacks: some available

continues to work,

able to process it.

and blocks,

able to, processes it, and sends a reply,

work.

35 0-8186-7882-8/97 $10.00 0 1997 IEEE

Page 2: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

concurrency within the client may be lost while it is blocked and inactive. The concurrency among objets is not effective if they spend a lot of time in waiting for each other, and processor time is lost by busy waiting [Agha ... 931. Another drawback is that long term transactions are impossible even if objets are persistent.

In the asynchronous request /reply protocol, the client does not blocks at the end of step i). It is allowed to continue to work while it is waiting for the result of a pending request, and this overcomes the inconveniences of the previous protocols: the requestheply nature of object communications is taken into account, and the maximal concurrency is supported. Moreover, message sending and synchronous request /reply prove to be special cases of this protocol: an object may not wait for the reply of a request (either the reply is lost, or the request is anonymous so that the server is warned that no reply is to be sent), and an object may suspend all its activities while it is waiting for a reply. Thus, asynchronous request /reply protocol is a higher model of 0-0 concurrency.

1.2. Intra-objet concurrency The inter-object concurrency makes possible the

- asynchronous request /reply protocol, and this latter, in turn, requires intra-object concurrency: in order that the blocking of one activity (which is waiting for a reply) does not block the object, it must have other concurrent activities which will continue. More generally, internal concurrency provides objets with the following capabilities:

i) as a client, an object can have several concurrently pending requests and wait for their replies, while its other activities go on;

ii) as a server, an object can concurrently process several requests;

iii) as being autonomous, an object can have a spontaneous activity which is not caused by requests servicing; in other words, it may be (pro)active and not only reactive [Manna.. .81].

It is clear that such capabilities increase the rate of concurrency within a system, and this is likely to speed the system’s execution up. In addition, unnecessary synchronisation constraints are avoided, and objets become free to organise the work they have to achieve; this favours the object autonomy and potential re-use, and makes the structure of objets and the code of their methods simpler. The avoidance of unnecessary constraints also decreases the possibilities of deadlock: when objets have many activities in progress, it is less likely that all these activities are blocked! For instance, if a client requests the pop service of an empty stack, the deadlock will be avoided if another activity of the client continues and then causes a request for the stack’s push service.

Now, concurrency within objets may be effective - an object is a multi-processes engine able to execute simultaneously several operations -, or it map be virtual - an object is able to process only one operation at once and its activities progress in turn. The difference is mainly a matter of performance, and effective concurrency

introduces difficulties in the design of an object, since its data need to be protected against its own concurrent accesses.

1.3. Cooperative Objects Cooperative Objects (COOs) are a formalism allowing

designers to model a system as a collection of such objets, which encapsulate their multi-threaded control structure and cooperate through an asynchronous request /reply protocol. These features are gained through the integration of concepts of the 0-0 approach and Petri nets, so that COOs have a high expressive power, including the modelling capabilities of both the 0-0 approach and Petri nets. Concepts of the 0-0 approach are used to define the general organisation of a system (classification and dynamic instantiation of components, encapsulation, distinction between the specification and the implementation, inheritance, dynamic linking and polymorphism) and also to define the data processing dimension of each component by means of instance variables and methods. So the designer has benefit from all the facilities given by this approach. As for Petri nets (PN), they are used to define the internal control structure of each object (intra-object concurrency), and the communication /synchronisation between objets (inter- object concurrency). So the designer benefits from the suitability of PN to deal with the reactive dimension of each object and with their synchronisation. PN are quite simple to use to define concurrent behaviours, because they are based upon the causality relationship, they have a well defined operational semantics, and they are graphic in nature. Moreover, the analysis techniques of the PN theory [Murata 891 may be used to check the properties and validate a COO system.

SYROCO (an acronym for SYstbme RCparti d’Objets CoOpCratifs) is an implementation of COOs. Each Object is implemented as an instance of a C++ class provided with a function which executes the PN of its control structure and accounts for the intra-object concurrency. As for the inter-object concurrency, it is supported by the underlying Operating System. The generated code is small and efficient enough to implement significant applications. On the other hand, facilities are given to the designer to finalise and manage the complexity of such applications; namely, the generated code may be well equipped, either automatically or in a specific way by the developer.

The next section of this paper introduces the COO formalism and shows a small example, while the third section gives an overview of SYROCO. Then concurrent features of COOs and their implementation in SYROCO are addressed.

36

Page 3: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

11. The Cooperative Objects formalism Cooperative Objects consider a system as being

System = Objects + Cooperation Object = Data structure + Operations + Behaviour

11.1. Overview of a COO system

defined by the following rules [Bastide.. .90, Sibertin 941:

So, the Object is the basic component of a system, and the whole system behaviour results from the behaviour of each Object and the way they cooperate. Identified by a name, an Object is equipped with attributes and functions for the processing of these attributes (the Data and Operations dimensions), and with a control structure which defines all its potential behaviours (the Behaviour dimension). This control structure is described by means of a High-Level Petri net, which allows an Object to have several concurrently on going activities; transitions occur one by one (this point will be discussed in section IV), but they may belong to different activities so that these activities progress in turn. The structure of each Object - its Data, Operations and Behaviour dimensions - is determined by the class of which it is an instance. Classes may be organised in accordance with several inheritance relationships which authorise the polymorphism and the sharing of items, but this aspect is out the scope of the paper.

A COO system is a collection of such Objects. The Cooperation dimension determines in which circumstances an Object of a certain class may interact with another one. These interactions obey a requestlreply protocol; interactions corresponding to a data flow are synchronous (when a client requests an operation, it blocks until the server provides a result), while interactions corresponding to a control flow are asynchronous (when a client requests a service, its other activities go on as long as they are not blocked). To a large extent, the Objects of a system are autonomous: they act concurrently and there is no central control. In addition, a COO system is open: during its evolution, new Objects can be dynamically created, yet some others can disappear.

The definition of a COO system needs to make use of a sequential programming language (preferably an 0-0 one) to define the System of Data Types shared by its Objects. This System of Data Types (SDT) includes a set of types which appear in the definition of COO classes. This programming language is also used to write the embedded code of Objects, that is the code of Objects’ operations and other pieces of code which appear in the control structure net. SYROCO uses the C++ language to define both the SDT and the embedded code.

Thus, defining a COO system consists of defining its SDT, the COO classes appearing in this system, and its initial configuration (the set of Objects composing the initial state of the system).

The formal semantics of COOS is defined in [Sibertin 941. Namely, it is possible to (automatically) build a single Petri net the behaviour of which is equivalent to the

system’s behaviour. This net makes explicit the behaviour of the whole system, including the service calls and the dynamic creation and deletion of Objects. Thus, the validation techniques of the PN theory may be applied at the level of each Object class, and also at the whole system level.

A COO class is composed of a set of attributes, a set of operations, a control structure net called its OBCS, and a set of services supported by this OBCS. We shall present these items, and Figure I shows an example of the definition of a COO class.

11.2. The Data and Operations dimensions Each attribute is typed either by a type of the SDT or by

some COO class, in which case its value is a reference towards another Cooperative Object. Some of these attributes are public whereas the others are private.

Operations are methods in the usual meaning. The types of their parameters belong to the SDT or are COO classes, and their code is written using the C++ language. Some of these operations are private, while the others are public.

Public attributes and operations of an Object may be used by other Objects in any place of their embedded code, and they allow for synchronous communications: reading the value of an attribute or calling an operation blocks the client until it gets a result. Thus, a public operation must be designed in such a way that, in any case, the Object is able to immediately provide a result.

11.3. The Behaviour dimension The control structure net of a COO is called its OBCS

(for OBject Control Structure). It is a Petri net with Objects [Sibertin 851, an extension of PN allowing to handle tokens which are complex data structure. An OBCS is made up of places, transitions and arcs, together with inscriptions describing how tokens are processed.

Places are the state variables of the Object. The type of a place either belongs to the SDT, or is a COO class reference, or is a list of such types. A place may contain zero, one or any number of t o k e n s of this type. Accordingly, a token is either a constant value, a reference towards an Object, or a list of those items. At any moment, the net state (or marking} is defined by the distribution of tokens onto places and the values of these tokens.

Transitions aim at changing the net state, that is the tokens’ values and locations. They are connected to places by oriented arcs, and variables labelling arcs act as formal parameters of transitions. They define the flow of tokens from input places to output places of transitions, and determine what tokens the transition action is applied to. A transition may be guarded by a precondition, a side-effect free boolean expression involving its input variables and Object’s attributes. A transition may include an acfinn which consists either of a request for a service of another Object, or of a request for the creation or the deletion of an Object, or of any piece of code in which calls for operations may take place.

Page 4: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

Class Stack specification; opegations empty ( ) : Boolean / / / return (top == O ) ; / / / ;

push (i: ITEM) : <>; pup ( 1 : <ITEM>;

s e m i ce s

end,

ClaCs Stack implementation; attxibutes

tup : int; buf : array [SIZE] of ITEM; aux : Stack*; //a reference toward another Stack

full 0 : Boolean begincode return (top == SIZE); endcode;

operations

I Init (n : const OCNAME&) //defines the instances' initial value

! (full0) t l buf[topl = i; top++ ;

t2 f u l l ( )

if ! (aux) { char* nom = gen-nom(); aux = create-Stack (nom);}

t5

3. push

= aux->push (i) ; <> < -

Figure 1 : Definition of a COO class

aux==NULL t4 <i> = aux-zpop() ; if (aux->empty()) top --;

i = buf[topl; if (Coodelete (aux) )

A transition may occur (or is enabled) if its input places contain tokens to which its input variables may be bound, in such a way that the precondition evaluates to true. The occurrence (or the firing) of an enabled transition changes the marking of its input and output places. Tokens bound to input variables are removed from input places. At that time, the action of the transition is executed. The transition

occurrence completes by creating tokens according to variables labelling output arcs, and putting these tokens into output places.

Executing an OBCS consists of repeatedly firing transitions which are enabled from the current marking, starting from the initial marking.

Page 5: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

11.3. Services Each Service of a COO is implemented by a couple of

places of its OBCS: an accept-place intended to receive tokens which are requests for the service (each token groups together the parameters of a call), and a result- place in which the client retrieves the result of its invocation, as soon as it is available. Thus a service request is treated by a sequence of transition occurrences: the first transition of this sequence takes the request token from the accept-place, while the last transition puts a token down in the result-place (In fact, result-places are implemented at the client side, so that the server sends the result-token to the client). Graphically, accept- and result- places do not appear in the OBCS, but transitions connected to them by an arc are pointed out by a dangling arc; of course, one transition may be both the accept- and return-transition of a service, as for the services of the example in Figure 1.

All services are public, and they support asynchronous communications since the server may need some delay to provide a result, either because the server’s current state disables the service or because processing the request requires a lot of work. A service call may take place only in the action of a transition. At the occurrence of such a transition, a token gathering the in-parameters is put into the accept-place of the server’s service; when the result token of this request is available, the transition retrieves it from the corresponding result-place and completes its occurrence. Thus, it is possible that the occurrence of a transition including a service request lasts some time until the server provides the result, but other transitions may occur during this time so that a client is not blocked by a service call. Indeed, the formal semantics of a transition including a service request is defined by splitting the transition into one transition for sending the request-token and one transition for retrieving the result-token, and connecting these two transitions by a waiting place which holds the request identifiers [Sibertin 941.

As a conclusion, the OBCS of an Object fully determines its behaviour:

the service requests it issues towards other Objects, as a client,

the availability of its services and how requests are processed, as a server, and

its spontaneous activity, as an autonomous Object.

11.4. The Cooperation among COOS Now, we can see how the Cooperation dimension of a

COO system is defined. Calls for synchronous communications may be located in any place of the embedded code; they are not isolated, without damage for the validation of the whole system behaviour since they introduce no synchronisation constraints. As for asynchronous communications, they are associated with the Behaviour dimension into OBCSs: indeed, the internal behaviour of an Object can not be dissociated from its asynchronous communications with others, since synchronisation constraints introduce a mutual dependence between these two dimensions: the state of Objects

determines when requests are issued, accepted and replied, and the availability of requests and replies determines the behaviour of Objects. Nevertheless, the call and the processing of services are implemented by specific items of OBCSs, so that the Cooperation and Behaviour dimensions may be clearly distinguished. At the syntactic level, the synchronisation code is clearly isolated.

Hence, the behaviour of a COO system results from the concurrent activity of its actual Objects. And the activity of each COO is twofold:

to process the calls for its public operations upon request, and

to execute its OBCS, that is to fire transitions which may occur, as a background task.

11.5. An example: a dynamic stack Syntactically speaking,.the definition of a COO class is

made up of a specification and an implementation. The specifcation of a COO class corresponds to its interface: it includes the definition of its public attributes and operations, together with the declaration of its services. On the other hand, the implementation of a class includes the definition of its private attributes and operations, and its OBCS. A COO class may be edited either as a text file (using a very simple syntax) or using the MACAO Petri net editor [Mounier 941 used in Figure 1. In the latter case, the MACAO file is translated into a text file.

As an example, Figure 1 shows the definition of the COO class Stack. A Stack is bounded as it can store only S I Z E items. But when it is f u l l and receives a push request, it creates an auxiliary Stack, and forwards to it the requests for the p u s h and pop services. Then, this auxiliary Stack is deleted if it becomes empty after a pop request. Thus, a Stack acts as if it was unbounded, or the root of a stack of bounded stacks.

The OBCS of this class features only one place, the type of which is empty: it may contain only raw tokens bearing no value. The tl and t 2 transitions accept the service push, and they are guarded by complementary preconditions. t l stores the item i and returns an acknowledgement, while t2 creates an auxiliary Stack if it does not yet exist, requests the push service of the aux Stack, and then returns an acknowledgement. The syntax of the service call means that no reply is expected for that request, that is t 2 sends the acknowledgement without waiting for the result of its request. Concerning the pop service, the t 5 transition waits for the reply of its request before send its own reply to the client.

By default, each service serves requests on a FIFO policy. To ensure that the pop service actually returns the last arrived ITEM, t l and t 2 have an higher priority than t 4 and t 5 .

The t l and t4 transitions both update the t o p attribute, and thus they cannot occur concurrently, and the same holds for the t2 and t5 transitions w.r.t. the aux attribute. We shall see in section IV that transitions of an OBCS never occur concurrently; thus this constraint is automatically enforced and it is pointless to add other places to ensure their mutual exclusion.

39

Page 6: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

III.SYROC0 SYROCO is an environment allowing to design COO

classes and to execute systems of COOs. The aim of this section is to give an overview of its main features.

SYROCO doubly relies upon the C++ language. On the one hand, the System of Data Types and the code embedded into Objects are written using this language; the SDT is so constituted with a set of C++ files, and it may refer to or include any C++ library. On the other hand, SYROCO generates C++ code so that it implements an Object as an instance of a C++ class. The generated code is very standard, and it may be compiled by most of the C++ compilers.

Each COO class gives rise to the generation of a C++ class, referred to as its COO++ class, in such a way that each COO Object is implemented as an instance of the corresponding COO++ class. Any COO++ instance inherits (among other things) a function which is an interpreter able to execute its OBCS. This generic “token game player” accurately implements the formal semantics of OBCSs and the asynchronous requestireply protocol: it repeatedly looks for transitions which are enabled by the actual marking and fires one of them, and sends the appropriate tokens when a service request or reply occurs. Details about the implementation of COOs as C++ objects may be found in [Sibertin. ..95a].

SYROCO increases the expressive power of COOs, by means of additional features which allow designers to finely control the behaviour of Objects. We briefly introduce these features.

Each COO owns a local clock; these clocks are synchronised on the occasion of communications caused by service requests and replies.

Arcs from place to transition are characterised by a minimum and a maximum delay; these delays indicate the minimum [maximum] length of time that a token must stay in the place in order to be involved in an occurrence of the transition.

Arcs from transition to place are characterised by a delay indicating the length of time between the transition occurrence and the arrival of the token in the place.

A priority level is associated with each transition. Hence a transition may occur only if it is enabled and no other transition having a higher priority is enabled.

Tokens of each place are ranked according to one of the four following policies: queue, FIFO, random, or any order relation (coded by the designer) accounting for the value of tokens.

An if-added daemon and an if-removed daemon may be associated with each place; they are coded by the designer, and are executed at each insertion [removal] of a token in [from] the place.

Each Object is provided with a supervising function which is called after each transition occurrence.

SYROCO also offers a debugging facility allowing the user to examine the state of the Objects’ OBCSs. This debugger does not deal with the embedded C++ code, but

with the Behaviour and Cooperation dimensions. Each Object has its own debugger, and it is possible to call the debugger of any Object from the debugger of another one [Hameurlain 961.

SYROCO includes a lot of compilation conditions enabling to compile COO++ classes in such a way that either they include many facilities to interactively control their behaviour and to get execution traces, or they are raw implementations, more efficient in space and time. The size of the code shared by all the COO classes of a system is around 60 K, whereas the own code of a class is mainly the embedded code provided by the designer. The memory required to allocate a new instance is a few K; for instance, the memory size required to allocate an instance of our Stack example varies from 0,5 to 1,2 K according to the number of compilation conditions.

The OBCS interpreter is very efficient, so that the overhead resulting of the synchronisation (executing the OBCSs and sending tokens) is negligible with regard to the execution of actions (in as much as they entail some amount of computation). As an example, let’s consider a complex Object which models a table of “dynamic” philosophers which may leave the table when they are satisfied, or be introduced at the table when they are hungry (this net, given in [Sibertin 941 and used as a case study in [OOPMC 961, includes 15 transitions and 18 places). Below are the performance measured on a SPARCclassic Sunstation and on a Windows NT PC (provided with a Pentium 120 processor, and using Visual c++ :

number of PC (Pentium transition Suns tation

occurrences 0.420 s 0.090 s

10 000 2.620 s 0.790 9

I 1000 000 I 240 s 1 7 0 s I This speed is independent of the size of the net, but it

depends on the number of tokens of the marking if the transition preconditions are strict. In this case, to decide whether a transition is enabled may require to test many bindings between the transition variables and the tokens staying into its input places.

There exist many other environments for the simulation of (high level) Petri nets; a description of most of them m a y b e f o u n d i n t h e s i t e http://www.daimi.aau.dk/PetriNets/tools. The main charac- teristics of SYROCO with regard to these systems are the following:

an original technique for the implementation of Objects’ OBCS, in a semi-compiled way, which provides the good performances of the interpreters;

the availability of many mechanisms allowing the designer to finely control the behaviour of each Object and of the whole system;

accounting for the data processing dimension of a system, and fully integrating this dimension with the control structure described by OBCSs.

40

Page 7: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

Due to these features, SYROCO may not only be used at the early steps of the design process of a system - as a tool for the simulation of conceptual models. It is also usable at the implementation step - as a distributed programming language.

IV. Concurrency This section discusses the model of concurrency

adopted by COOs and details how it is implemented in SYROCO.

IV.l. What kind of concurrency ? The semantics of COO is defined in the framework of

the PN theory, but PNs support several interpretations of concurrency [Peterson 8 11 and they entail indeterminism issues.

According to the interleaving semantics, transitions occur one by one: if several transitions are enabled from the actual marking, only one of them is chosen to occur. In this case, a PN interpreter fires transitions sequentially and the net parallelism is virtual. According to the true paral- lelism semantics, several transitions enabled by the actual marking may occur simultaneously in a single step, provided that they may remove different tokens from their input places. In this case, a PN interpreter may fire several transitions simultaneously and the net parallelism is actual. Of course, these two semantics are tightly related and, up to an ordering of the fired sets of transitions, the same sequences of transitions may occur in both semantics.

The execution of a PN also requires to cope with the indeterminism resulting from the choice of the (set of) transition(s) which will occur. This indeterminism happens when two transitions are both enabled by a same token staying in a shared input place (e. g. transitions t4 and t5 in Figure 1). Whatever is the considered semantics, the transitions are in conflict and the interpreter has to choose the one of them which will occur. In the interleaving semantics case, the indeterminism may also be caused by independent transitions (e. g. transitions t2 and t5 in Figure 1). Even if they may occur concurrently, the interpreter has to choose which of them will occur first.

In PNs with valued tokens, there is another kind of in- determinism resulting from the choice of the input tokens involved in a transition occurrence. Indeed, in the case where several tokens are staying in the input places of a transition, there may be many ways to bind the transition variables to tokens.

The management of indeterminism is an important feature, because it must ensure the fairness of systems’ execution, that is: if, in an infinite execution, a transition mav occur infinitely many times, then it mustoccur infinitely many times. If the execution of a system is not fair, its behaviour may feature some anomalies or not match its expected behaviour because some capabilities of the system remain unused.

An environment supporting the execution of COO systems has to choose between the two semantics of con- currency, and between various ways to deal with indeter-

minism. These choices must be made both at the internal level of each Object and at the level of the whole system. We shall argue that the interleaving semantics is better for the intra-object concurrency, while the true parallelism semantics is better for the inter-object concurrency. As a consequence, when several processors are available each Object can get a processor but no Object requests several processors. Formally speaking, a COO system is equivalent to a single (huge) PN, and one may wonder what is the resulting semantics for this net. It turns out these choices result in a nice true parallelism semantics: transitions may occur concurrently if (1) they are concurrently enabled (each one takes its own tokens), and (2) for each transition, the values of the tokens which refer to Objects are different (thus an Object can not be involved in several concurrently occurring transitions).

IV.2. Intra-Object concurrency Concerning the intra-object concurrency, COOs adopt

the interleaving semantics, and the PN interpreter of each Object fires only one transition of its OBCS at once. Thus, a COO may have several on going activities (according to the number of transitions enabled from the current marking), but they progress in turn.

The first reason for this choice is a conceptual one. Due to this semantics, the action of each transition is a critical section, and the occurrence of a transition is atomic with regard to other transitions. Thus the designer is relieved of ensuring the mutual exclusion of transitions even if their actions refer to the same attribute. In the Figure 1 example, places for enforcing the mutual exclusion of transitions t 1 and t4, and t2 and t5, are necessary if the true parallelism semantics is assumed. As a consequence, an Object needs to synchronise with other Objects according to the logic of its behaviour, but it does not need to synchronise with itself (and protect its attributes against itself) since it never concurrently accesses its own data structure. In other words, an Object is a whole; it is encapsulated w.r.t. other Objects, but it is not divided into encapsulated parts.

The second reason is related to performance issues. On the one hand, a true parallelism interpreter suffers from some overhead: to prevent the occurrence of several transitions with the same token, it must synchronise accesses to the marking of places connected to the occurring transitions. On the other hand, the true parallelism improves the performance only if several processors may be allocated to the interpreter of each Object, that is, if the number of available processors is much greater than the number of Objects in the system (remind that the true parallelism among Objects is assumed). This is a very strong assumption, and would entail an additional overhead to dynamically decide how many processors to allocate to each Object.

As a consequence of choosing the interleaving seman-

distributed on several nodes of a computer network. But this seems to be a slight constraint, insofar as a real encap- sulation of a distributed object is very difficult to ensure.

tics for the intra-object concurrency, an Object cannot be

41

Page 8: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

SYROCO

inter-Object distribution concurrency

C++ 3 $ 4 $8 0

+environment

1

Operating System Figure 2: The links of SYROCO with its underlying environment

About indeterminism, the default strategy of the OBCS interpreter is a fair one. For the sake of efficiency, it fires the first found transition together with the first found tokens. Fairness is gained by the random nature of the search, in such a way that one may consider that it randomly chooses the transition and the tokens.

IV.3. Inter-Object concurrency Concerning the concurrency among Objects, the default

strategy is the true parallelism; in other words, several Objects may be active at the same time and fire a transition (each Object fires a transition of its own OBCS). This strategy causes no synchronisation overhead, since no place is shared by the OBCSs of different Objects; thus, if the interpreter of an Object finds an enabled transition, it may fire it without regard for the choices made by the interpreters of other Objects.

The true concurrency among Objects allows for using COOs for the implementation of distributed systems, different Objects being running on different nodes. And when several Objects are located on a same node, they may run on different processors (provided that several ones are available). Thus, this choice allows for making an effective use of the resources of the computing environment.

But coping with true concurrency entails implementa- tion issues. One solution is to develop a specific runtime system which provides the functionalities required to support true concurrency. The other solution is to rely upon the underlying operating system, using its capabili- ties as well as possible, and so does SYROCO. Indeed, the current operating system technology provides high-level and general purpose mechanisms which fit well the needs of COOs. In addition these mechanisms are already implemented in a quite reliable and efficient way, and their (re)use obeys the “separation of concerns” principle: Figure 2 shows that different dimensions of COOs are supported by different mechanisms. In return, SYROCO must account for the actual services offered by operating systems, and thus it generates three kinds of COO++ classes for different computing environments: for a C++

I i

compiler upon a sequential operating system, for environ- ments supporting threads, and for COOL, a Distributed Computing Environment compliant with CORBA. The sequential version

The sequential version of SYROCO implements the interleaving semantics among Objects. Thus, the concur- rency between Objects is only virtual. To this end, SYROCO includes a scheduler which randomly chooses one Object among the actual Objects of the system; then, it activates this Object by calling its interpreter for a given number of transition occurrences (this number accounts for the work load of the Object). In this version, the interpreter returns as soon as no transition is enabled, since only the activation of another Object may make a transition to become enabled.

Object deletion raises a difficult problem in Concurrent object-oriented Languages. First, a Cooperative Object has its own activity, thus the absence of references to it from other Objects is not a reason for its deletion; thus SYROCO includes no garbage collection mechanism. Then, the asynchronous nature of inter-object communications makes that an Object must not be deleted while it is processing a service request or waiting for the result of a service request; in the first case, the client would never receive the result, and in the second case the result sent by the server would be lost. Thus, an Object will refuse to delete itself if it is engaged in some asynchronous communication as a server or as a client. The threaded version

SYROCO implements the true parallelism semantics by delegating the underlying operating system to activate Objects, according to the computing resources. This raises no difficulty, since there is no conflict between Objects: the occurrence of a transition in an Object never prevents the occurrence of any transition in another Object.

In the threaded version, all Objects are running into the same process, but each one in its own thread. To be more precise, making active an Object causes the creation of a new thread, and the Object interpreter is executed inside this thread, referred to as the main thread of the Ob.ject.

42

Page 9: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

The overhead for spawning new threads is small, since it threaded version enables to focus upon the concurrency only occurs at the creation of a new Object. As a among Objects, while avoiding issues related to the distri- consequence, each Object is accessed by several threads: bution and persistency of Objects. Finally, the COOL ver- 1. its main thread, sion enables to implement a COO system as an open and 2. the threads of Objects calling a public operation or decentralised system composed of autonomous Objects. reading the value of a public attribute, The following table summarises the features of the three 3. the threads of client Objects putting parameter-tokens versions of SYROCO with regard to inter-object into accept-places in order to request services, 4. the threads of server Objects putting result-tokens in order to return the results of service requests.

Each COO++ includes a mutual exclusion lock for

the OBCS data structure, namely the place markings. As

cross i n

ensuring that threads 1, 3 and 4 do not concurrently access

for Object attributes, the designer is fully aware how they are accessed by threads 1 and 2 ; thus, it is his duty to protect them against concurrent accesses, by including appropriate get and release statements into the embedded code of transition actions and operations. To ease this task, a specific lock is automatically set during the execution of the action of any transition; if each operation requests this lock, then operations and transition actions never occur concurrently, and the resulting behaviour is very close to the behaviour of the sequential version.

Contrary to the sequential version, the interpreter does not return when no transition is enabled, but it waits until it receives a token from a thread 3 or 4. In order to avoid busy waiting, the interpreter blocks on a specific lock which is released at the arrival of a parameter-token or result-token. The COOL version The third version of SYROCO is supported by COOL (the Chorus Object-Oriented Layer, [Lea.. .91, Chorus 941). COOL is an environment built upon the distributed operat- ing system CHORUS which provides 0-0 applications with a Distributed Computing Environment and is compliant with the standard CORBA [OMG 9-51. The COOL version of SYROCO relies on the same principles than the threaded version, and in addition each COO++ also becomes a COOL Object. Due to the functionalities provided by COOL, the COO-COOL Objects of a system can run on different nodes of a network (COOL takes in charge remote communications in a transparent way), and they include functions to migrate from one site to another and to manage their persistency. All the facilities provided by COOL are quite easy to use, since the embedded code of Objects can use the COOL API to exploit its functionalities.

From a software development point of view, every one of these three versions of SYROCO is useful to finalise a COO system. The sequential version enables designers to test and validate the behaviour of each Object (the OBCS interpreter is the same in the three versions), and how they cooperate in an asynchronous way by token sending; but problems related to concurrent accesses to the Object data structure are taken apart, since the concurrency between Objects is virtual. The main difference between a sequential and a threaded execution of a COO system is that, in the latter case, the execution of transition actions may be interrupted by operations and vice versa. Thus, the

Message crossing is the possibility for two objects to send messages to each other, each one ignoring that the other also sends a message. This results in a sequence: object 01 sends 02 message m l ; object 02 sends 01 message m2; 02 receives m l ; 01 receives m2. Delay of routing refers to the length of time between the sending of a message and its reception by the target object. Finely, the order of messages may be preserved or not.

V. Conclusion Cooperative Objects are an attempt to base the

concurrent dimension of Concurrent Object-Oriented Languages upon Petri nets, one of the formal theory of concurrency together with CCS [Milner 801 and the temporal logic [Kroger 871. They obey the principles of the 0-0 approach, and integrate PN into Objects while preserving the fundamentals of both theories. Due to this tight integration, COOs provide designers with a few concepts and mechanisms for coping with concurrency and inter-object communication which (1) are at a high conceptual level (so they ease the designer’s understanding of the system’s and Objects’ logic), (2) have a wide expressive power (so they ease the detailed design) and (3) have a simple and well-defined semantics (so they are easy to use in a reliable way). As an advantage among others of these features, we have experienced that the definition of a COO class is very concise and quite easy to understand, as the reader may judge from the Stack example given in Figure 1 (remember that the logic of this class is not as simple as it may seem at the first glance).

SYROCO attempts to establish that COOs may be implemented in an efficient way, so that they are convenient for the modelling, the validation and also the implementation of open and distributed applications. The main features of SYROCO which enable to reach this goal may be summarised as follows:

SYROCO implements the semantics the asynchronous request /reply protocol in a very rigorous and direct way. As this semantics is quite simple, the generated code of COO++ classes is efficient, and in addition the developer may understand what is happening when hetshe is faced to an unexpected behaviour.

43

Page 10: [IEEE Computer. Soc. Press Second International Workshop on High-Level Parallel Programming Models and Supportive Environments - Geneva, Switzerland (1 April 1997)] Proceedings Second

SYROCO follows the principle of separation of concerns which is a basic feature of COOs. To be more precise, SYROCO requires a C++ environment (for the Data and Operation dimensions) and an Operating System (especially for the inter-object concurrency), and its use of these components is well confined both from a syntactical and conceptual point of view (cf. Figure 2). In addition to portability benefits, the developer is never surprised by unexpected side-effects and helshe can reason upon a separation of concern basis.

SYROCO is also an open environment fully integrated with the C++ language. This provides the developer with the possibility to reuse C++ classes and libraries, to act upon the SYROCO’s kernel from the embedded code, to define COO classes which inherit from C++ classes, etc., and more generally with the flexibility of this language to deal with particular situations encountered in any real application.

Finally, SYROCO is a convenient and comprehensive framework to be used both as a simulation tool for high level models of systems and as a programming environment for applications. For instance, it is used at SEPT (Service d’Etdes communes de la Poste et de France Ttltcom, Caen, France) for the development of workflow applications. This results from the fact that the basic concepts of COOs stand at a high conceptual level, and from the easy to use means provided by SYROCO to finely control the behaviour of each Object.

References [Agha ... 931 G. AGHA, S. FROLUND, W.Y. KIM,

R. PANWAR, A. PATTERSON, D. STURMAN Abstraction and Modularity Mechanisms for Concurrent Computing. Research Directions in Concurrent Object-Oriented Programming, G. Agha, P. Wegner & A. Yonezawa Eds, MIT Press, 1993.

[Bastide ... 901 R. BASTIDE, C. SIBERTIN-BLANC Object-Oriented Design of Parallel Systems. 2nd international Workshop on Software Engineering and its Applications; Toulouse (F), December 1990.

COOL V2 Programmer’s Guide; Feb 1994.

ContrGle de l’ex6cution d’objets CoOpCratifs dans I’environnement SYROCO. Proceedings of CRAC’96, Journtes de Recherche sur le ContrGle RBparti dans les Applications Cooptratives, Universitk Paris VI, 30-31 May 1996.

[Kaiser ... 891 G. E. KAYSER, S. S. POPOVITCH, W. HSEUSH, S. F. WU MELDing multiple granularities of parallelism. 3rd European Conf. on object-oriented Programing, Cambridge University Press, Nottingham (UK), July 1989

Temporal Logic of Programs. ETACS Monographs on Theoretical Computer Science 8, Berlin, Springer-Verlag, 1987.

[Chorus 941 CHORUS SYSTEM.

[Hameurlain 961 N. HAMEURLAIN

[Kroger 871 F. KROGER

[Lea.. .91] R. LEA, J. WEIGHTMAN Supporting object oriented languages in a distributed environment: The COOL approach. Proceedings of TOOLS USA’91, Santa Barbara, July 1991.

The Temporal Framework for Concurrent Programs. In The Correctness Problem in Computer Science, E. Falkenberg & J. More eds, Academic Press, 1981.

A Calculus of Communicating Systems; Lecture Notes in Computer Science 92, Springer-Verlag, 1980.

The MACAO Reference Manual. MASI Lab, June 1994.

Petri Nets : Properties, Analysis and Application. Proceedings of the IEEE, vol77, No 4, pp 541-580, April 1989.

Common Object Request Broker: Architecture and Specification. Published by the Object Management Group and WOpen, Reference OMG.9 1.12.1

ORBIX 2, Reference Guide, Release 2.0. November 1995, IONA Technologies Ltd Publisher.

[OOPMC 961 G. AGHA, F. DE CINDIO & A. YONEZAWA (Eds)

Concurrency, Workshop within the 17th Intern. Conf. on Application and Theory of Petri Nets; Ozaka (J), June 1996.

[Peterson 8 13 J. L. PETERSON Petri net theory and the modelling of systems. Prentice Hall, Englewood (New Jersey), 19981.

High Level Petri Nets with Data Structure. Proceedings of the 6th European Workshop on Application and Theory of Petri Nets; Espoo (Finland), June 1985.

Communicative and Cooperative Nets. Proceedings of the 15th International Conference on Application and Theory of Petri Nets, LNCS 815, Springer- Verlag, 1994.

N. HAMEURLAIN, P. TOUZEAU A C++ implementation of Cooperative Objects: Proceedings of object-oriented Programming and Models of Concurrency, G. Agha & F. De Cindio Eds, Workshop within the 16th Intern. Conf. on Application and Theory of Petri Nets; Turino (I), June 1995.

[Manna.. .81] Z. MANNA, A. PNUELI

[Milner 801 R. MILNER

[Mounier 941 J.-L. MOUNIER

[Murata 891 T. MURATA

[OMG 951

[Orbix]

Object-Oriented Programming and Models of

[Sibertin 851 C. SIBERTIN-BLANC

[Sibertin 941 C. SIBERTIN-BLANC

[Sibertin.. .95] C. SIBERTIN-BLANC,

44