Consider an example of a vending machine that requires a user to insert a coin and ... Illustrating Fan-In and Fan-Out Effect Via Connect for Vending Machine.
ISBN: 978-972-8924-30-0 © 2007 IADIS
SPECIFICATION OF ASYNCHRONOUS COMMUNICATING SYSTEMS (SACS) A. S. Bavan1, E. Illingworth2, A. V. S. Rajan1 and G. Abeysinghe1 1
School of Computing Science Middlesex University The Burroughs London NW4 4BT, UK United Kingdom 2 School of Computing and Mathematics London Metropolitan University 100 Minories London EC3 1JY United Kingdom
ABSTRACT This paper presents the Specification of Asynchronous Communication System (SACS), a formal notation that is used to specify an asynchronous message passing system which uses point-to-point communication. SACS is a modified version of a synchronous variant of the Calculus of Communicating System (CCS) known as the Synchronous Calculus of Communicating Systems (SCCS). The basic aim of this technique is to separate communication from computation so that these two activities can proceed independently as far as possible. Except for the asynchronous nature, the communication is assumed to be point-to-point as in SCCS. These design techniques allow the programmer to develop programs that are virtually free of livelock and deadlock conditions. SACS complies with four design rules which emerged from our experience in developing distributed applications using a message passing language called Language for Implementing Parallel/distributed Systems (LIPS). KEYWORDS
Asynchronous message passing, Synchronous message massing, point-to-point communication, distributed applications, deadlock, livelock.
1. INTRODUCTION Processes running on different processors in parallel and distributed systems rely on some form of message passing to exchange data. This can be achieved either synchronously or asynchronously and has obvious advantages and disadvantages. The advantages include secure data exchange, control over the computation and data flow, deadlock and livelock avoidance, and improved performance. Regardless of the type of the system, a good design tool can assist in developing an implementation that is reliable and satisfies the original requirements. CSP (Communicating Sequential Processes) (Hoare 1978) and CCS (Calculus of Communicating Systems) (Milner 1982, Milner 1983) are well established formal notations that are suitable for specifying distributed applications. SCCS (Gray Sep 2000) is a synchronous variant of CCS. By applying restrictions to the manner in which the SCCS is used, a formal notation has been developed to specify an asynchronous message passing system that uses point-to-point communication. These restrictions are in the form of four design rules that guarantee reliable message passing, a technique which is lacking in asynchronous message passing systems. These rules originate from a language called LIPS (Language for Implementing Parallel/Distributed Systems) (Bavan 2001) which has been designed by the first author to implement parallel and distributed systems.
274
IADIS International Conference Applied Computing 2007
As the main objective of this paper is to describe SACS which has its origins in LIPS, it is appropriate to give a brief overview of LIPS which is done in Section 2. An introduction to the design of distributed systems using the restricted SCCS notation is presented in Section 3. Section 4 concludes the discussion.
2. AN OVERVIEW OF LIPS LIPS is an asynchronous message passing parallel programming language which has the following features: • Communication by assignment, • Separation of communication from computation, • A data flow nature coupled with asynchronous message passing, • Portability.
2.1 Basic Elements of LIPS Programs A LIPS program is represented by a network of computational nodes connected by a set of point-to-point unidirectional channels that carry messages between communicating nodes. The syntactic structure of a LIPS program is: PROGRAM ; BEGIN END. A network definition describes the topology of the program by naming each node and its relationships to other nodes in the system. A node can be described as a distributable object which can receive or send messages. It consists of one or more guarded processes which perform computations using the data that arrive as input and produces output that is sent to other related nodes. A LIPS program consists of an obligatory host node and other nodes in a network where the host node is executed first. Each node consists of a set of guarded processes. The guard (precondition) of a corresponding process has to be satisfied for that process to become eligible for execution and only one process can be executed at any point in time. A guard is a list of input channels waiting for the data to be received. The syntax for a node definition is as follows: Node name() ->() { ; : } The syntax for a guarded process is as follows: [, .., ] => { } As the objective is to specify the communication between the nodes, the description on LIPS is bounded to network definition. Detailed description of LIPS can be found in Bavan & Illingworth (2001).
2.1.1 Network Definition Network definition describes the topology of the network using a set of connect statements that specifies the communication between the nodes in a LIPS program. This statement specifies a name of the node to be executed in the network and its input and output (I/O) channels. It does not specify how such I/O channels are linked to the rest of the system. The syntax of the connect statement is as follows: node_label:connect node_name(input_channels) -> (output_channels)
275
ISBN: 978-972-8924-30-0 © 2007 IADIS
An example of a connect statement that links two input channels, a and b, to a node that executes a process P with a node label 7 and produces an output on channel c is shown in Figure 1.
a b
c
P
[7]: connect P([a, b]) -> ([c])
Figure 1. The Connect Process
The square brackets are used to group data belonging to a particular data type or category. Using the connect statement networks of any complexity can be built. For a given problem, the connect statements can be used to build a dataflow graph to represent the solution without the need for a specification of the computation at network level. This promotes good design practice by motivating the programmer to produce the target solution model at a higher level of abstraction using communication as the framework thus separating computation from it. Consider an example of a vending machine that requires a user to insert a coin and press a button, after which the machine will make and serve a drink. This scenario can be further developed by allowing a user to order more than one drink. In this case, the user may repeat the above behaviour a number of times or alternatively order all the drinks (by continuing to insert coins and press buttons) before removing any served drinks, allowing them to queue up their orders and then remove the drinks as they are delivered. A pictorial specification for this problem is depicted in Figure . We have split the vending machine into Machine_interface and Machine_internals to explain the fact that there are two processes involved in modelling the vending machine. One can combine them into one process at the expense of loosing vital information which is important in understanding the behaviour of the intended system. The init process is the host node in this case, which will send the trayEmpty signal to the Machine_internals and terminate. init
Customer
trayEmpty
deliver
coin button Machine_ Interface
sig1
Machine_ Internals
Figure 2. Network Diagram Illustrating Fan-In and Fan-Out Effect Via Connect for Vending Machine
The set of link statements for the vending machine problem under discussion can be stated as follows: [1]: connect host ([]) -> ([trayEmpty]); [2]: connect Customer ([deliver]) -> ([coin], [button]); [3]: connect Machine_Interface ([coin], [button]) -> ( [sig1]); [4]: connect Machine_internals ([trayEmpty], [sig1]) -> ([deliver]); The following section describes the four design principles to be adopted to perform asynchronous message passing using SCCS.
3. THE FOUR DESIGN RULES Communication between concurrent processes can be effectively specified using process algebra. Process algebra could be considered as an efficient method of specification at an abstract level and verification because of its expressiveness and strong theoretical foundations. The main algebraic approaches to
276
IADIS International Conference Applied Computing 2007
concurrency include CCS, CSP, and SCCS. Research is being carried out on the formal specification of concurrent and real-time systems. Fencotts’s (1996) work on CCS and Roscoe’s (Roscoe 1998) exploration on CSP are few of them. Since the inception of CCS, it has undergone many changes (Gray Sep 2000, Milner 1983, Milner 1985, Astesiano & Zucca 1984, Engberg, U. & Nielsen, M. 1986). SCCS, which is the main focus of this paper, is a real-time algebra (Gray 1999, Milner 1983) which contains the notion of time at the most primitive levels of actions and interactions. It is possible to significantly relax some of the conditions which are applied to control the behaviour of processes in the system without loosing their properties. This can be demonstrated by considering a simple example in which two processes exchange data. We can express this in SCCS notation as follows: A = x! : y? : A B = x? : y! : B The above definitions imply that process A outputs a value x and waits for a response on channel y from process B. There is no restriction on combining the input and output channels at the same location within a SCCS specification. The equivalent definition using the same notation in our approach is specified as shown below: A = 1 : A_BDY_1 + y? : A_BDY_2 //1 before the ‘:’ denotes an idle event A_BDY_1 = x! : A A_BDY_2 = 1 : A B = x? : B_BDY_1 B_BDY_1 = y! : B This means both processes, A and B, deliver their output on virtual channels, x and y, and call themselves. The input channels guard a computational unit of code (a body of code). When each input channel in a specific guard has received an item of data, the associated body of code is executed. In the example given above B_BDY_1 is a body of code guarded by x?. Each body of code transforms the input data into output data and is passed onto other nodes in the system. Input channels occur before a body of code, which in turn occur before output channels. Consider the traditional concurrency problem, Producer_Consumer, which may be expressed as: PRODUCER = 1 : PRO_BDY PRO_BDY = ∂y! : PRODUCER // where ∂y implies that there is a rule that replaces ∂y by //1:∂y + y and in this case ∂y! = 1 : ∂y! + y! CONSUMER = ∂y? : CON_BDY CON_BDY = 1 : CONSUMER This can be analysed as given below: SYSTEM = PRODUCER x CONSUMER where ‘x’ is the concurrency operator. = 1 : PRO_BDY x ∂y? : CON_BDY = 1 : PRO_BDY x (1: ∂y? + y?) : CON_BDY = 1 : (∂y! : PRODUCER x ∂y? : CON_BDY ) = 1 : ((1 : ∂y! + y!):PRODUCER x (1: ∂y? + y?) :CON_BDY ) = 1 : 1y : (1 : PRO_BDY x 1:CONSUMER) The PRODUCER generates data and passes it to the CONSUMER for disposal. Two major issues are raised in this example which require further explanation. The first is that SCCS uses a synchronous approach to message passing operations, i.e. the send/receive pairs have to synchronise when they pass a message among themselves. Due to this synchronous message passing intercommunication, the Producer_Consumer problem effectively transfers the data in lockstep. The second issue is that a synchronous notation is being used to create an asynchronous model. The idler (1) introduces delays into the system so that the send/receive pairs can synchronise. One delay (∂) proposition is defined as: ∂E = 1 : ∂E + E This leads to the first design rule. Before stating the rule, let us describe the SACS-TEMPLATE which is represented as follows:
277
ISBN: 978-972-8924-30-0 © 2007 IADIS
Process_ag ent_1 = input_ch1_ 1[[. | : | +] input_ch1_ n] : Process_ag ent_1Bdy_1 + … + [input_chk _1[[. |:| +]input_chk _n] : Process_ag ent_1Bdy_k ] Process_ag ent_1Bdy_i = output_ch1 _1 [[. |:| +]output_ch 1_n] : [@ | Process_ag ent_1]
where i ranges from
1 to k
Process_ agent_1 is the template representation of a software process. The input_ch represents one instance of the many possible input channels within a software node. A body of code transforms input data into output data, then the output data is sent onto other nodes in the system via output channels. Using SACS terminology a body of code is guarded by input channels, implying that data must arrive at every channel in the guard before the body of code executes. Consider the following example: A = x?.y?:A_BDY_1 + a?:b?:A_BDY_2 + (m?+n?):A_BDY 3 A_BDY_1 = v!.w! : A A_BDY_2 = c! : d! : A A_BDY_3 = (o! + p!) : A x?, y?, a?, b?, m? and n? are the input channels of process agent A. v!, w!, c!, d!, o! and p! are the output channels of process agent A. x? and y? must synchronise simultaneously with x! and y! ( not shown ) because they are separated by the ‘.’ operator. a? and b? must synchronise sequentially with a! and b! (not shown) because they are separated by the ‘:’ operator. Either m? or n? must synchronise with m! or n! (not shown) because they are separated by the ‘+’ operator. Once all the input channels guarding a body of code have synchronised (i.e. received data) the body of code executes. Each of the input channels of one specific guard can be separated by SIMULTANEOUS AND ‘.’, SEQUENTIAL AND ‘:’ or the OR ‘+’ operators. The output channels can also be combined using the same operators. The idler operator can replace either input or output channels, implying that internal processing is occurring at this point. This can be considered as a Boolean TRUE event. In SCCS terminology, the agents A_BDY_1, A_BDY_2 and A_BDY_3 represent three different bodies of code within Node A. Any process defined using SACS notation may be terminated by the inaction agent (@). This is illustrated by the following example: B = s? : B_BDY_1 B_BDY_1 = 1 : @ In this example when data arrives via the s input channel the body of code B_BDY_1 processes it and then the node B terminates. A system consists of several interacting process agents. Rule 1 - Every process agent in a concurrent system operates in an iterative fashion and obeys the SACSTEMPLATE. This means every node in the system should consist of one or more guards that contain input ports followed by a body of the code and then by output ports. Rule 1 implicitly states that a concurrent system is made of autonomous processes that intercommunicate using message passing. The SACS-TEMPLATE described should clarify Rule 1. Rule 2 - A channel must have one input port and one output port only. Point-to-point communication is being used for this style of design. Thus fan-in and fan-out are special examples that must be specified explicitly. Consider the following example for fan-in: A = ∂y1?. ∂y2? : A_BDY_1 A_BDY_1 = 1 : A B = 1 : B_BDY_1 B_BDY_1 = ∂y1! : B C = 1 : C_BDY_1 C_BDY_1 = ∂y2! : C This can be analysed as:
278
IADIS International Conference Applied Computing 2007
SYSTEM = A x B x C = ∂y1? . ∂y2? : A_BDY_1 x 1:B_BDY_1 x 1:C_BDY_1 = (1:∂y1? + y1?).(1:∂y2? + y2?): A_BDY_1 x 1:B_BDY_1 x 1 : C_BDY_1 = 1: (∂y1? . ∂y2? : A_BDY_1 x ∂y1! : B x ∂y2! : C) = 1: ((1: ∂y1? + y1?).(1: ∂y2? + y2?): A_BDY_1 x (1: ∂y1! + y1!): (1: ∂y2! + y2!) : C) = 1: 1y1.1y2 : (1 : A x 1:B_BDY_1 x 1:C_BDY_1)
B x
Notice that true concurrency in operation in the above example. The channels y1 and y2 are synchronising simultaneously and not sequentially. Consider the example below for fan-out: A = 1 : A_BDY A_BDY = ∂y1!. ∂y2! : A B = ∂y1? : B_BDY B_BDY = 1 : B C = ∂y2? : C_BDY C_BDY = 1 : C This can be analysed as: SYSTEM = A x B x C = 1 : A_BDY x ∂y1? : B_BDY x ∂y2? : C_BDY = 1:A_BDY x (1: ∂y1?+y1?):B_BDY x (1: ∂y2?+y2?):C BDY = 1(∂y1! . ∂y2! : A x ∂y1? : B_BDY x ∂y2? : C_BDY ) = 1((1: ∂y1!+ y1!).(1: ∂y2!+ y2!):A x (1: ∂y1?+y1?):B_BDY x (1: ∂y2? + y2?):C_BDY ) = 1: 1y1.1y2 : (1 : A_BDY x 1:B x 1:C) Again, note that true concurrency in operation in the above example. The examples on Fan-in and Fan-out raise an important issue about the use of SCCS to model asynchronous behaviour. When two channels are grouped together, should they synchronise simultaneously or in sequence? This is really a design issue and it is up to the designer. However, it should be noted that even if each of the above examples were coded to synchronise in sequence, the fan-in and fan-out examples would still work (i.e. they would not deadlock). The delay operator ∂ would effectively introduce delays into the system to allow channel synchronisation. Rule 2 affects on the choice of input channel names. If the same name is used more than once within a process definition then mutual exclusion does not apply and results in an operational/implementation paradox. Rule 3 - An input channel cannot be shared by two or more guarded processes in a node. If an input channel is shared by more than one guarded process, it may lead to partial or total starvation of one of the guarded processes. It also will lead to deadlock due to the propagation effect created by starvation. The following example: A = ∂y? : A_BDY_1 + ∂y? : A_BDY_2 is invalid in our modified use of SCCS notation since the same channel y is being used as input guard for two different processes within a node. Rule 4 - A self-contained system must include at least one idler operator in an input channel position. A self-contained system is one which does not have channels which cross the application domain. The implication is that a non self-contained system will have one or more channels with just one port. All the examples in this paper are self-contained systems. An application with channels crossing the boundary is considered part of a cluster-based system. The examples of SACS-TEMPLATE design show how difficult it is to prove that they will not end in deadlock. Even the use of software tools (e.g. Concurrency Work Bench [8]) does not solve the problem because the CWB can not process large-scale specifications.
3.1 Validating SACS-TEMPLATE based designs using Set Theory Deadlock can be detected in a SACS-TEMPLATE model using set theory. We have proven that the SACSTEMPLATE and the design rules will result in deadlock free systems. However, an empirical view can
279
ISBN: 978-972-8924-30-0 © 2007 IADIS
supply confidence in the set theoretic validation approach. When data does not cross system boundaries, the system is self-contained. An idler operator will have to start the system. The idler will trigger the execution of a body of code which will result in data being passed by output channels into the system. Since channels can only occur in input/output port pairs, data will flow around the system provided every input port has a corresponding output port and vice versa. These input and output sets should be pre-processed to find idler actions (1). If any process is found to contain an idler action, that part of the model should be checked for algorithmic error. Note that a selfcontained system (one that does not have any channels crossing its boundaries i.e. all channels with both ports) must have at least one idler action. If all the idler actions are now removed, all the input channel sets are combined to form a SYSTEM.in_ch set and all the output channel sets are combined to form a SYSTEM.out_ch set, the system can be validated for avoidance of deadlock. If (SYSTEM.in_ch\SYSTEM.out_ch) ∪ (SYSTEM.out_ch\SYSTEM.in_ch) = ∅, then every channel consists of an input port and output port pair. The system is unlikely to deadlock and is self-contained. That is what happens in the vending machine problem discussed in Section 0. One possible formal specification of this model using SACS is shown in Figure 3. Notice that the specification contains the signal trayEmpty, without such a signal the vending machine would continuously accept coins and buttons from the customer and deliver a drink without checking whether the previously served drink had been removed. This would result in a vending machine that would deliver drinks on top of each other. To remove this erroneous behaviour, we have synchronised the action of delivery of a drink by introducing the trayEmpty signal. This signal is given an initial value by the INIT process. //Init simply send a machineReady once and terminate INIT = trayEmpty!:@ //customer can put a coin followed by a button press any number of times CUSTOMER = 1:coin!:Button!:CUSTOMER + deliver?:CUSTOMER //mc1 responsible for receiving coin and button will deliver a signal (sig1) //for each pair of coin and button in that order MACHINE_INTERFACE =1:coin?:button?:sig1!:MACHINE_INTERFACE // mc2 makes the drink only when it receives sig1 andtrayEmpty (i.e when //the cup dispenser is free) MACHINE_INTERNALS = (sig1?.trayEmpty?):deliver!:MACHINE_INTERNALS // Define the system SYSTEM = INIT x CUSTOMER x MACHINE_INTERFACE x MACHINE_INTERNALS Figure 3. Specification of Vending Machine
Note that @ is an inaction agent i.e. nothing happens after @. In order to verify this example will not deadlock using simple set theory, one must collect all the input channels for each process into a set and do likewise with all the output channels. INIT.inch = {1} INIT.outch ={∂trayEmpty!} CUSTOMER.inch = {1, ∂deliver?} CUSTOMER.outch = {coin!, Button!} Machine_Interface.inch = {coin?, button?} Machine_Interface.outch = {sig!} Machine_internals.inch = {∂sig1?, trayEmpty?} Machine_internals.outch = {deliver!} The set of all input channels in the specification is: I = { coin?, button?, sig1?, trayEmpty?} The set of output channels in the specification is: O = { coin!, button!, sig1!, trayEmpty!}
280
IADIS International Conference Applied Computing 2007
Applying the classification criteria i.e. (I/O) ∪ (O/I) will detect any channels that do not occur as input – output pairs. In other words, (I/O) ∪ (O/I) = null. In addition to being a self contained system, it also does not interact with other sub-systems on the network. We attempt to prove that a system should obey the four design rules and follow the SACS template style for the design of distributed systems to reduce the possibility of a deadlock.
4. CONCLUSION This paper describes the formalisms supporting LIPS using examples to illustrate the features of LIPScompliant programs for successful point-to-point inter-computation in distributed systems. The paper also outlines the four key elements of a design pattern for LIPS-compliant programming. Thus, the four rules form a framework for successful concurrent program design process in the context of point-to-point intercommunication patterns. A set theoretic validation technique is used as an alternative to the manipulation of SCCS propositions. The result is a simple verification technique that can detect logical errors in a proposed SACS-TEMPLATE based design. This technique can also classify a design as either selfcontained or cluster-based. A CASE tool that could translate a SACS-TEMPLATE based design into JAVA is planned for the future.
REFERENCES Astesiano, E. & Zucca, E. 1984, Parametric channels via Label Expressions in CCS, Journal of Theoret. Comp. Sci., vol. 33, pp. 45-64. Bavan, S. & Illingworth E. 2001, A language for implementing parallel and distributed systems using asynchronous point-to-point communication, Nova Science Publishers, Inc. Commak, NY, USA, pp. 109-129. Engberg, U. & Nielsen, M. 1986, A calculus of communicating systems with label passing, Computer Science Department, University of Åarhus. Fencott, C. 1996, Formal Methods for Concurrency, International Thompson Computer Press. Gray, D. 1999, Introduction to the Formal Design of Real-Time Systems, Springer Verlag. Hoare, C.A.R. 1978, Communicating Sequential Processes, Communications of the Association of Computing Machinery, vol. 21, no. 8, pp. 666-677. Milner, R. 1985, Seminar on Concurrency, , eds. S.D. R.Brookes, A.W. Roscoe & G. Winskel, SpringerVerlag. Lecture Notes in Computer Science, Berlin, pp. 197-221. Milner, R. 1983, Calculi for Synchrony and Asynchrony, Theoret. Comp. Sci., vol. 28, no. 3, pp. 267-310. Milner, R. 1982, A Calculus of Communicating Systems, Springer Verlag, New York Inc.,. Roscoe, A.W. 1998, Theory and Practice of Concurrency, Prentice Hall.
281