^2003^ next_inactive up previous


COST: Cost-of-Service Tracking in AsmL



by
Rupak Das



\includegraphics[scale=0.5]{MonashCrest.eps}



Submitted by Rupak Das
in partial fulfillment of the Requirements for the Degree of
Bachelor of Software Engineering with Honours (2770)
in the School of Computer Science and Software Engineering at
Monash University




Monash University
November, 2003



©Copyright by Rupak Das, 2003


Contents


List of Figures

  1. Abstract States of a Sorting Machine
  2. The Counter Interface
  3. The Counter Class
  4. The Stack Interface
  5. The Stack Class
  6. A Stack Run
  7. Stack Initialisation
  8. RPN Calculator Execution Trace
  9. The Abstract `Philosopher' Class
  10. The `Table' class
  11. Dining Philosophers Interface: Initialised State
  12. Dining Philosophers Interface: Deadlock State
  13. Reader Class in AsmL
  14. Writer Class Extract in AsmL
  15. User Interface for Reader-Writer
  16. Execution Trace of Readers-Writers Implementation
  17. Display Counters
  18. Proposal: Cost Syntax Example
  19. Special Commenting Syntax for AsmL Pre-processor
  20. Pre-processed Code in AsmL


\begin{thesisabstract}
\par Abstract State Machines (ASM) decompose a computer s...
... of having built-in counters in the AsmL distribution.
\par\end{thesisabstract}


\begin{thesisacknowledgments}
I would like to thank Prof. Heinz Schmidt for his ...
...neering, and my fellow BSE and BCS honours students.
\end{thesisacknowledgments}

Introduction

As different software development strategies evolve, executable specifications are being introduced as the starting point in a software life cycle. Executable specifications have reduced development and testing costs of large-scale software projects, and have increased the stability of software systems at the same time (Modeled Computation LLC; 2001). Over the last decade, the Abstract State Machine (ASM) approach has been proven suitable for large-scale executable specifications of realistic systems in several application domains. Microsoft Research's Foundations of Software Engineering (FSE) group, led by Yuri Gurevich, developed the Abstract State Machine Language (AsmL). AsmL is a high-level programming language that implements the Abstract State Machine paradigm (Gurevich; 2001), and helps to develop mathematically precise specifications of computer systems.

In building component-based systems, prediction and measurement of extra-functional properties of components have been elusive goals (Schmidt; 2001). Extra-functional execution properties such as performance (time), re-usability, reliability, availability, security, and responsiveness have not received much attention in terms of building executable specifications. These properties generally influence the cost-of-service of large-scale software systems. Specification of such extra-functional properties, and the impact on implementation of the executable specifications has not, as yet, been explored in great detail. While ASMs and AsmL address the basic, behavioural and synchronisation properties of a software specification, they do not address the above-mentioned quantitative extra-functional properties (Barnett and Schulte; 2001b).

The cost-of-service incurred due to extra-functional properties could be estimated to a certain extent by introducing tracking variables in executable specifications. Variables that track extra-functional properties could be specified, and measured during execution of the specification. Similar cost-of-service tracking variables could also be introduced in the implementation of the specification. Such a COST measure could help to bridge the gap between ASMs, AsmL and extra-functional properties, and at the same time lead to cost reduction of software development.

It should be noted however, that measuring the executable specification cost and measuring the actual implementation cost have entirely different meanings. The execution-time of the specification can be expected to be much worse compared to that of the implementation. For example, measuring and predicting time as an extra-functional property via executable specifications could therefore mean performing a symbolic calculation. Such a calculation would be made in terms of some justifiable time calculus calculated alongside the symbolic execution of the specification. These calculations will become a reference model and can be recorded in a similar way to the computation outcomes recorded for correctness proofs and checks. A testing approach would be taken when comparing the measured implementation costs (execution-time in this case) to those of the reference model. If the actual implementation measures disagree with the modeled properties, such violations can then be pinpointed so that the responsible parts (such as components or functions) of the system can be identified.

Outline

This project explores the development process of executable specifications based on the ASM paradigm. Such executable specifications are usually developed using AsmL. The ASM thesis and paradigm as propounded by Yuri Gurevich is discussed to provide a background to this project in chapter 2. The features of AsmL as a high level specification language are reviewed in chapter 3. Chapter 4 discusses the cost-of-service of software systems and extra-functional properties that influence such costs. Past approaches to estimate and track extra-functional parameters are brought forward. The relevance of these approaches to executable specifications written in AsmL is also explored. Counter variables and the counter interface is introduced in chapter 5, and their relevance to cost-of-service tracking is discussed. Chapter 6 details the different case studies undertaken during the project. Different solutions to well-known problems that were developed are presented. The observations made during these case studies are described and the COST Proposal is presented. An analysis of the work done and scope of future work is then presented in the concluding chapter.

Abstract State Machines

Background

The notion of evolving algebra as a new computation model was discovered by Yuri Gurevich as early as 1988. The emphasis of this formal method was to adapt Turing's thesis by focusing on the dynamic and resource-bounded aspects of computation (Gurevich; 1998). Evolving algebras were later renamed as Abstract State Machines. Gurevich (2001) writes about the questions that led him towards a new computation model:
What is it that we study in computer science? What is computation? What are the peculiar dynamic systems of computer science? Thinking about these questions, I arrived at the notion of abstract state machine (ASM) as a formalization of the notion of computer system at any given level of abstraction.

Decomposing a computer system into a hierarchy of abstraction levels composed of states and operations was the initial purpose of Abstract State Machines. Since its inception, the concept has been the subject of various researches in different application domains including finite model theory, complexity theory and applied computer science (Börger; 2000).

The ASM Thesis

Gurevich (1985) first propounded the ASM Thesis, which was eventually published as the Sequential Abstract State Machine Thesis (Gurevich; 1999). The ASM Thesis, as stated by Gurevich (2001) is as follows:

Let A be any computer system at a fixed level of abstraction. There is an abstract state machine B that step-for-step simulates A.

The dynamic nature of a computer system is due to the fact that it has a state that evolves in time (Gurevich; 2001). An abstract state of a system is the representation of a system's state at any given instant. The evolution of a system from one state to the next is achieved by applying update rules to the current state of the system. The transition from one state to the next is called a step. The complete evolution of a system, from a starting point to the point where no more changes occur, is called a run.

A very simple example of an ASM model would be to consider a sorting machine that sorts an array using a single-swap algorithm like bubble sort or quick sort. For an unsorted array $A$, where $A(x)$ is the array value at index $x$, sort can be defined as:

        choose x,y in indices(A) such that x < y and A(x) > A(y)
            do
                A(x) := A(y)
                A(y) := A(x)

The value of $A$ at each step is the state of the machine. The rule warrants the selection of any two indices, $x$ and $y$, that satisfy the given conditions, $x < y$ and $A(x) > A(y)$. This is followed by the swapping of array values at the chosen indices. The sorting ASM executes until no further updates are possible. No further updates are possible when the array is sorted (Modeled Computation LLC; 2001).

A diagrammatic representation of such a run would be:

Figure 2.1: Abstract States of a Sorting Machine
\includegraphics[scale=0.7]{asm02.eps}

Use of ASMs

Initially, the ASM thesis was used to solve problems related to the dynamics of programming languages. Egon Börger tried out the ASM approach to model the dynamics of PROLOG (Börger; 1990b; Börger; 1990a). The ASM approach led to ISO standardisation of the language. This was followed by the application of ASMs for specification and verification of machine architectures and protocols. The abstract and operational nature of ASMs led to its rapid success in developing executable specifications (Börger; 2000). The use of evolving algebras, and later ASMs, in hardware and software engineering, particularly for high level analysis and design was further investigated by Egon Börger (Börger; 1995,1999).

ASMs were used at Siemens Corporate Technology to design a railway process model named FALKO (Börger et al.; 2000). Barnett et al. (2000) discuss the use of ASMs at Microsoft by providing a relevant case study. A noted product group within Microsoft that uses ASM technology is the Universal Plug and Play group (Foundations of Software Engineering; 2003a; Glässer et al.; 2001). The last decade has seen ASMs being used primarily to develop executable specifications for complex software systems.

Relevant Tools

A number of tools used to write and execute ASMs have been developed in academia (Huggins; 2003). XASM (Anlauff; 2000) is a noted open source project. Tools used successfully at Siemens are ASM Workbench (Del Castillo; 1998), and ASM Gofer (Schmid; 2001). However, none of these existing tools could be moulded to the software development environment at Microsoft, specifically COM (Microsoft Corporation; 2002) and the .NET (Microsoft Corporation; 2003) platform. To this end, the Foundations of Software Engineering group at Microsoft Research, led by Wolfram Schulte, developed an executable-specification language called AsmL (Foundations of Software Engineering; 2003b).

AsmL: The ASM Language

COM and .NET

The Component Object Model (COM) architecture developed by Microsoft is a language- and machine-independent standard to build component-based applications. COM components each have a unique identity, and an API that exposes interfaces (Barnett et al.; 2000). A client of a COM component accesses its functionality by means of the interface. Each interface comprises of a set of methods, and where appropriate, new types and enumerations as parameters.

The .NET framework is built around the idea of the Common Language Runtime (CLR), which accepts code written in different languages and converts it to executables in the .NET framework. The CLR is an execution environment that promotes interoperability between different languages by means of a rich object-oriented class library. .NET software components are distributed in the Microsoft Intermediate Language (IL), which is executed by the CLR (Gordon and Syme; 2001). All .NET aware languages are compiled into IL, but are then re-compiled into native binary machine code at execution time. The Common Type System (CTS) of the .NET platform describes all possible types supported by the CLR, and their representation in the .NET metadata format. Languages that use the Common Language Subset (CLS), a subset of the CTS, are called .NET aware languages.

Executable Specifications

Model-based Specifications

Sommerville (1995) defines Model-based specification as:

Model-based specification is an approach to formal specification where the system specification is expressed as a system state model. This state model is constructed using well-understood mathematical entities such as sets and functions. System operations are specified by defining how they affect the state of the system model.

Specifications are descriptions of how software components are supposed to work once they are implemented. Executable specifications add to the notion of traditional model-specifications by having a single and unambiguous meaning (Modeled Computation LLC for Microsoft; 2002a).

The ASM Approach

The mathematical model of a system's evolving state, expressed in terms of an ASM, gives the executable specification its meaning. As discussed in Chapter 2, ASMs provide a step-for-step model of a system's evolving state at any given level of detail. Specifications written based on the ASM model hence become executable by simulating the step-for-step behaviour. This provides the user with a human-readable and machine-executable model of the system's intended operation in a minimal and complete way with respect to any given user-defined level of abstraction (Modeled Computation LLC for Microsoft; 2002a). An executable specification is minimal in a way that it only models the constraints and behaviour that all correct implementations of the system will have in common. The fact that ASMs are powerful enough to describe non-deterministic behaviour helps in this regard.

Simulation and Testing

Apart from being able to specify any real-world computer system faithfully, the executable nature of specifications written using AsmL can also be precisely simulated. This lets both the user and the developer play around with the design before implementation commences. Benefits of this include (Modeled Computation LLC; 2001):

The whole process of writing executable specifications in AsmL therefore influences the testing of the system in a positive way by initiating testing much earlier in the software development life cycle.

Features of AsmL

The original theory of ASMs as mathematical objects was extended to provide a solid semantic foundation for AsmL (Gurevich et al.; 2001). AsmL thus has a strong notion of formal semantics which provides the mathematical foundation to a software specification. The intrinsic theory of ASMs that lies beneath AsmL helps it to faithfully model the abstract structure and step-for-step behaviour of complex software systems as mentioned earlier in Section 2.2 (Modeled Computation LLC for Microsoft; 2002b). Features of AsmL as a specification language are as follows (Barnett et al.; 2001; Modeled Computation LLC; 2001; Modeled Computation LLC for Microsoft; 2002a):

The AsmL specification language can be used to specify COM components and interfaces. AsmL also uses the CLS, thereby ensuring that contracts written using AsmL can be used seamlessly across all .NET aware languages (Barnett and Schulte; 2002). Microsoft currently uses AsmL for modelling, rapid prototyping, analysing, checking of APIs, devices, and protocols (Barnett and Schulte; 2001a).

Cost-of-Service

Extra-functional Properties as Cost Attributes

The functionality of a software system can be gauged by answering the question: what does the system do? On the other hand, extra-functionality can be defined by answering the question: how does the system interact with the processing environment with respect to attributes that can be observed, such as performance, re-usability and reliability? Franch (1997) points out that extra-functional issues have generally been given less importance than functional issues. Functionality of a software system has always been the primary focus. As a result, formal specification languages and methods have focused more on specifying functional properties of a software system.

Extra-functional issues have been approached in two ways in the past: process-oriented and product-oriented ways (Landes and Studer; 1995; Mylopoulos et al.; 1992). A product-oriented approach deals with extra-functionality at component level. Components come together with a description of services provided, and the signatures of the methods that provide the services. However, the specifications provided with components often lack information regarding interactions beyond interface compatibility. As a consequence, the extent of prediction and verification of system properties get restricted (Vieira et al.; 2001).

The extra-functional characteristics of software components are not always as apparent as functional properties. This often results in specifications that have not taken into account extra-functional issues. Such a specification becomes unbalanced and can lead to unexpected maintenance costs due to flawed design. Changes in system environment that occur during maintenance often modify the extra-functional conditions. These changes can also have a direct influence on the cost of maintenance as the extra-functional situations now need to be reviewed in light of the new system conditions (Franch and Botella; 1997).

Importance in Executable Specifications

The above-mentioned system development and maintenance costs that are incurred due to neglect of extra-functional properties can be negated by introducing cost-of-service tracking attributes in executable specifications. Being able to estimate the cost-of-service for a particular extra-functional property during specification would help decrease the overall cost of the software system.

The ability to reason about system properties based on the external abstractions of components would give specification developers a new added advantage. In this regard, Issarny et al. (1997) put forward the idea of QoS (Quality of Service) relating to extra-functional execution properties such as availability, security and responsiveness that depend largely on the processing environment. Lau (2001) talks about the difference between a posteriori and a priori reasoning and why the latter is more important and relevant when it comes to specifying software systems. Lau (2001) opines that ``pre- and post- conditions (with only proof-theoretic semantics) are not enough for specifying interfaces. Rather, we need declarative (e.g. model-theoretic) semantics''. Some work has also been done to predict system dependencies in component access points (Vieira et al.; 2001).

ASMs and Extra-functional Properties

Little has been done to model the class of extra-functional properties that relate to the cost-of-service of a software system. Franch (1997) introduces a notation to express non-functional characteristics of software components called NoFun. Related work was done by the GESSI research group at the Universitat Politécnica de Catalunya (Botella et al.; 2001; Salazar-Zárate et al.; 2002; Franch and Botella; 1997; Universitat Politécnica de Catalunya; 2003; Franch and Botella; 1996). However, similar notions have not been introduced in executable specifications.

Schmidt and Zimmermann (1994) proposed different cost annotations for Object-Oriented (OO) Machines and applied them to OO Programs written in the Sather language. These authors also introduced a prediction calculus that is based on specific cost annotation measures. Such annotations are embedded in pre- and postconditions as Cost variables which keep track of the desired extra-functional properties. The primary aim of such abstract annotations were to provide a good basis for traditional software metrics. OO Machines, have a basis of algebra and are closely related to ASMs. This makes it possible to carry the cost annotations forward to a similar ASM model, something that has not yet been done.

Syntax and Semantics

Counter Variables

Extra-functional properties are often difficult to isolate as they are highly influenced by the interaction between different system properties. However, all extra-functional properties of a software system are caused by object methods in one way or another. An abstract measure of a particular extra-functional property can be calculated by tracking entrance and exits to and from methods. Tracking can be done on a scale of individual methods, or can be extended to work for objects where all member methods of an object are being tracked.

It was decided that counter variables will be associated with methods to keep track of different cost-of-service attributes. Every method has its own space and time complexity information. Counters enable the developer to estimate the number of times a method will be called in a correct and practical implementation of the specification. These factors can be scaled from a method perspective to a high-level object perspective. If such a mechanism can be put in place for all methods, a realistic prediction about the cost-of-service of a software specification can be gained. For example, `space' complexity can be tracked on a method level by counting memory allocation, `time' can be tracked by counting execution cycles, and `throughput' can be tracked by counting transactions per unit time of an object.

We propose three types of counters with the following syntax for the case studies to be conducted as part of this research project:

The `N' at the beginning is an abbreviation for `number of'. This is followed by the type of counter: `Req' for request, `Beg' for begin and `End' for end counters respectively. In all the above cases, the `methodname' is replaced by the actual name of the method. Counters should be declared and initialised for methods that will be used frequently and can be thought of as having a considerable impact on the cost-of-service. These counters can also be used to establish class invariants. For example, a stack-based program cannot have more requests made to the pop function compared to the push function.

The Counter Interface

Barnett and Schulte (2001b) discuss member variables of stateful interfaces in regards to AsmL. Also known as model variables, they are not part of the signature of an AsmL interface, but are only provided to give meaning to the method bodies. Such variables have also been called `auxiliary variables' in the past (Kleymann; 1999). Model variables are accessible only through the methods defined in the containing interface and its subtypes.

To introduce counters as cost-of-service tracking variables in executable specifications, we create a counter interface definition called ICounter in AsmL as shown in figure 5.1.

Figure 5.1: The Counter Interface
\includegraphics[scale=0.8]{ICounter.eps}

The declaration and initialisation of counter variables for methods are made easier with the introduction of the counter interface. Each method would have counter object(s) declared by means of this AsmL interface. The interface methods can also be used to increase, decrease and retrieve the value of a counter object. Object-oriented standards of AsmL.NET are maintained in the process. Dealing with counters as a cost-of-service tracking measure becomes easier as a result.


The Counter Class

The ICounter interface as discussed earlier is implemented in the Counter class. The Counter class defines the methods declared by the ICounter interface, and operates on the interface variables. The CounterValue() method returns the current value of the counter variable associated with the caller object method. The Increment() method increments the object method counter by one and the Decrement() method decrements it by one. The simplicity of the Counter class makes it very easy to understand and use as a cost-of-service tracking measure. The Counter class is implemented in AsmL as shown in figure 5.2.

Figure 5.2: The Counter Class
\includegraphics[scale=0.8]{CCounter.eps}

Counters and COST

A specification written using AsmL can be refined to produce an implementation in a three-step process as follows:

  1. Abstract Interface in AsmL
  2. Abstract Implementation in AsmL
  3. Concrete Implementation (in C#)

For the purpose of this research project, it was decided that counters would be used as a cost-of-service tracking measure on separate case studies. AsmL model specifications would be written and then refined to concrete implementations. The presence of counters in the specification and execution models would provide us with a measure of cost-of-service. We aimed to use cost-of-service measures introduced in specification models from the implementation to express a consistent cost measure. If the cost-of-service results tracked during specification-time execution were found to be similar to the results tracked during implementation-time execution, then the application of counters as a cost-of-service tracking measure would be proved successful. The feasibility of this approach could then be analysed, and further extended and scaled for larger and complex software solutions. The next chapter discusses the case-studies that were undertaken as part of this research project.

Case Studies

It was initially decided that counters will be introduced into the examples that accompany the AsmL for Microsoft .NET distribution as case studies for this project. This would let us build on the existing example specifications, instead of having to elicit requirements and specifications for a new problem. Based on the assumption that the provided example specifications are optimised in every possible way, introducing the aspect of cost-of-service into these specifications for the purpose of this research project would help in analysing results without having to take usual optimising factors such as efficiency and appropriateness of the specification into account. Out of the many provided examples, the `Stack' model was chosen as the first case study. The `Dining Philosophers' solution was extended to include counters as the second case-study. Lastly, a solution to the `Readers and Writers' problem, dependent on counters as an assertion measure to implement synchronisation, was developed.

The Stack Model

A stack is a Last-In-First-Out (LIFO) data structure that has three actions: Push, Pop and Top. The state of the stack model is contained in a variable that is declared as a sequence of integers. We extend the stack specification provided as an example with the AsmL for Microsoft .NET distribution (Foundations of Software Engineering; 2003c) to a stack interface called IStack. The stack interface is then implemented as the Stack class where all the methods are defined. Stack objects are then instantiated to write a Reverse Polish Notation Calculator executable specification in AsmL.

The Stack Interface

The stack model for the purpose of this case study is modeled as a stack of integers. The IStack interface written in AsmL, as shown in figure 6.1, declares a sequence of integers that reflect the state of the stack. The Push(), Pop() and Top() methods are also declared, and the corresponding pre-requisites defined. The Push() method takes in an integer as an argument, and pushes that integer onto the stack. The Pop() method pops the topmost element from the stack. To pop an element from the top of the stack, there needs to be at least one or more elements in the stack. This pre-condition of the Pop() method is declared in the IStack interface. The Top() method returns the value of the topmost integer in the stack, without popping it off the stack. Similar to the Pop() method, this method also requires the state of the stack to be non-empty. A pre-condition to this end is declared in the IStack interface.

Figure 6.1: The Stack Interface
\includegraphics[scale=0.8]{IStack.eps}

Three counter objects are declared for the Push(), Pop() and Top() methods. Due to the simple and sequential nature of a stack object, only `end' counters that are responsible for keeping track of finished executions of the relevant methods are declared. As detailed in section 5.1, the names of the method follow the type of counter that is being declared. The number of elements popped off a stack cannot be greater than the number of elements pushed onto the stack. This invariant can be confirmed by declaring an interface constraint that depends on counters. We establish the invariant by making sure that the `end' counter of the Push() method is always greater or equal to the end counter of the Pop() method. The code inside the boxes in figure 6.1 indicate the declaration of counters and the interface constraint in AsmL.


The Stack Class

The Stack class defines the methods that are declared in the IStack interface. The Push() method of a stack is responsible for pushing an element onto the top of the stack. In this case study, an additional step is added to the specification of a Push() method. After pushing the current element onto the stack, the `end' counter is incremented before execution of the method is completed. Similarly, after popping an integer from the stack, the `end' counter of the Pop() method is incremented before execution of the method is completed and control returns back to the caller. The Top() method returns the topmost element of the stack to the caller. Hence the `end' counter of this method is incremented before control is returned back to the caller. Although associating a counter with the Top() method might initially be akin to a futile exercise, careful and clever use of this counter can provide interesting measures as is illustrated in the Reverse Polish Notation Calculator implementation. Figure 6.2 shows the Stack class written in AsmL.

Figure 6.2: The Stack Class
\includegraphics[scale=0.9]{CStack.eps}


Reverse Polish Notation Calculator

A Reverse Polish Notation Calculator (RPN Calculator) uses a stack data-structure to perform basic mathematical operations. For the purpose of this research project, we implemented a scaled down version of a RPN Calculator. A Calc class was written in AsmL that instantiates a stack object as defined earlier, and pushes ten integers ranging from 0 to 100 into the stack. The integers are selected in a non-deterministic fashion. Basic mathematical operations are then performed on these integers according to user input. To perform an addition, subtraction, multiplication or division, the user enters the corresponding operator. Two integers are popped off the stack, the required operation performed, and the result pushed back onto the stack. If the user wants to view the result of the most recent operation, the `=' pops the topmost element off the stack, which is the result of the last operation.

This RPN calculator specification written in AsmL iterates nine times, and exits after the user has been given the chance to perform nine operations on the stack elements. Since the stack is initialised to have ten elements, more than nine mathematical operations performed on the stack would lead to assertion violations. Before stopping execution, the program displays all the counter values that have been measured during execution. Detailed source code listing of the Reverse Polish Notation Calculator specification written in AsmL can be found in appendix A.1.

Observations

The Stack class, as defined in section 6.1.2, was first tested using a test stub that is listed in appendix A.2. This was done to illustrate the assimilation of COST counters and normal stack operations as detailed in the stack specification. A stack object was initialised, five integer elements were pushed onto the stack, and then popped off the stack in last-in-first-out order. Figure 6.3 is a screen-shot of the results produced. It can be observed that the number of pushes and pops that happen during the test execution correspond to the counter values. The interface constraint, which is declared as the number of pushes has to be always greater than the number of pops, is also maintained. Apart from manually counting the output lines, this can be also observed by the fact that no runtime exception is thrown by the program in execution.

Figure 6.3: A Stack Run
\includegraphics[]{stackRun.eps}

A stack object was instantiated to implement the RPN Calculator as mentioned in section 6.1.3. Figure 6.4 is a post-initialisation screen-shot of the Stack-based RPN Calculator written in AsmL as a case study for this research project. Ten integers between 1 and 100 have been pushed onto the stack, and the program is waiting for user input.

Figure 6.4: Stack Initialisation
\includegraphics[]{rpn01.eps}

The program accepts nine user inputs, as the stack is initialised to have ten integer elements. Figure 6.5 is a screen-shot of a sample execution of the program that accepts user inputs and produces corresponding outputs. It is observed from this execution that the operations defined in the Stack and the Calc class work as expected. The counters are incremented at the end of each member method execution, thereby enforcing the interface invariant for the IStack interface. It is also noted that the number of executions of Push() is greater than the number of executions of Pop().

Figure 6.5: RPN Calculator Execution Trace
\includegraphics[scale=0.7]{rpn02.eps}

From the above observations, we can infer that the counter variables associated with each method provide a frequency measure of the method in question, and hence can be used as a cost-of-service tracking measure on a large-scale. Nine mathematical operations on a RPN Calculator executes the Push() method 16 times, and the Pop() method 15 times. Similar data retrieved during specification-time execution can provide an estimation of the resources likely to be used by a method during the course of a program execution. Such estimations can also be scaled to provide similar estimates for actual implementations of the specification in question.

Dining Philosophers

The dining philosophers problem, as described by Dijkstra (1972), is a common distributed systems problem, and is widely used as a benchmark for testing various aspects of concurrent languages, and effectiveness of concurrent design topologies. The ability of AsmL to execute atomic transactions helps in authoring solutions for different concurrent systems problems. An AsmL specification of the dining philosophers problem is provided with the AsmL for Microsoft .NET distribution by Microsoft. The specification solves both the greedy philosopher and the generous philosopher problem, illustrating the `deadlock' and `starvation' properties respectively.

Classes, Methods and Variables

As a case-study for this research project, we modified the dining philosophers problem specification to include counters as a cost-of-service tracking measure. The specification consists of an abstract Philosopher class. Each philosopher has a status, an index, and two methods - move() and canMove(). We add request, begin and end counters for the move() and canMove() methods to the abstract definition of a philosopher class. A displayCounters() method is also added to monitor the values of the counters after each move executed by the philosopher.

The implementation has five philosophers vying for five forks when their respective status is `Hungry'. A philosopher loops through the following states: Thinking, Hungry, HungryWithLeftFork and Eating. A philosopher requires both the forks to his/her left and right to commence eating. A structure called Fork is declared to denote a solitary fork, and a Set of forks is declared for the philosophers. Two methods left() and right() return the index of the corresponding forks of a philosopher. A philosopher has no forks while his/her current status is `Thinking'. A thinking philosopher becomes hungry and tries to procure the left fork, followed by the right fork. A philosopher can attain the `Eating' status only if both forks have been acquired. After eating for a while, the philosopher goes back to the `Thinking' state. Figure 6.6 shows the abstract Philosopher class written in AsmL.

Figure 6.6: The Abstract `Philosopher' Class
\includegraphics[]{philo01.eps}

A Table class is defined that controls the philosophers, and interacts with the external interface created in C#. A Table has a Set of Philosophers and a Map data structure to store relations between a Fork and a Philosopher. This class defines a Move() method, which acts as a global entry point to the AsmL specification from external implementations, such as the C# interface described later. The Move() method chooses a philosopher that can change state and executes a move() operation on that philosopher.

We introduce request, begin and end counters for the Move() method to track the number of times the philosophers are moved by a Table object, and also to track the number of external accesses performed on this AsmL specification. The Move() method also has a variable stepNo that is incremented after each execution of a philosopher move. Although the stepNo variable serves similar purposes as the counter variables, we retain this variable in our specification to perform comparisons with the counters that are introduced. Figure 6.7 shows a section of the Table class written in AsmL. The code inside the boxes indicate the initialised counters and their application as a COST measure.

Figure 6.7: The `Table' class
\includegraphics[]{philoTable.eps}

The counter variables are declared for the different key methods as mentioned earlier, and are incremented as and when required in the AsmL specification. Globally accessible methods that return the values of the counters in the Table class as string variables are also defined. This is to facilitate access to the counters from the external C# interface. We introduce COST counters only to the `greedy' philosophers solution provided in the example, and do not retain the `generous' solution due to the limited scope of this research project. A full code listing of the dining philosophers specification written in AsmL for the purpose of this research project can be found in appendix B.1.

The Interface

The sample specification for the dining philosophers problem implement a basic graphical user interface to demonstrate the different states of the philosophers and forks. We modify the existing interface by adding a button to display the counter values associated with the Table object. Figure 6.8 shows the interface after it is initialised. The console screen on the background displays outputs from the AsmL specification directly, whereas the window titled `Dining Philosophers' displays output from the C# interface. The close interaction between .NET compliant languages and their interoperability is demonstrated in this case-study. A full code listing of the interface written in C#.NET can be found in appendix B.2.

Figure 6.8: Dining Philosophers Interface: Initialised State
\includegraphics[scale=0.8]{dp01.eps}

A square with a `P' denotes a `Thinking' philosopher in figure 6.8. Small squares marked with an `F' indicate forks in the interface as shown in figure 6.9. A square marked with a `P', and that has only one fork attached to it indicates a `Hungry' philosopher. If a square marked with `P' has both left and right forks attached to it, then that philosopher is currently in the `Eating' state. Clicking on the `Display Counters' button populates the text-box on the right hand side of the window as seen in figures 6.8 and 6.9. Before a `Move' or a `Run' is executed, all the counters associated with the Table class have the value zero as illustrated in 6.8.

Clicking on the `Move' button executes the Move() method of the Table object, which in turn moves a philosopher that is ready to move and change its state in the life-cycle. A sequence of these moves constitute a run. Each move made by a philosopher is tracked by the associated counter variable, and is displayed in the console by the AsmL specification as seen in figure 6.9. A deadlock situation is reached when each philosopher has acquired one fork and is waiting for the next fork. The `greedy' nature of this solution ensures that a philosopher does not release a fork before he/she has finished eating. Hence the possibility of a deadlock remains. Figure 6.9 illustrates a deadlock situation. The console displays the number of moves executed by each philosopher so far, and the `Dining Philosophers' window displays the counter values associated with the Table object.

Figure 6.9: Dining Philosophers Interface: Deadlock State
\includegraphics[scale=0.8]{dp04.eps}


Observations

The `greedy' dining philosophers reach a state of deadlock as expected. The counters introduced as cost-of-service tracking measures keep track of the number of times each relevant method is being called. In this case-study, we retrieve the number of moves made by each philosopher by using the associated counters. Similarly, we retrieve the number of moves executed by the Table object in terms of the associated counters.

As illustrated in figure 6.9, Philosopher 1 has made 137 moves, Philosopher 2 has made 149 moves, Philosopher 3 has made 113 moves, Philosopher 4 has made 121 moves, and Philosopher 5 has made 113 moves before the program has reached a deadlock state. Individual moves of philosophers add up to a total of 633, whereas the total number of moves the Table object tried to initiate were 638. The Move() method in figure 6.7 indicates a choose statement that is evaluated as part of each execution. A philosopher that is in a position to change his/her current state is chosen as part of this evaluation. The above observation where the total moves executed by philosophers is 633, and the total number of moves initiated by the Table object is 638 affirms the non-deterministic nature of the Move() method.

It can be observed from this case-study that integrating external components written in .NET aware languages, with classes written in AsmL, is not extremely difficult. The fact that counters used as cost-of-service tracking measures in AsmL specifications can be easily used and extended as part of a concrete implementation is also illustrated. It is also observed that counters can be used to track the number of times a globally accessible method is accessed by external components. The value displayed after `Step #' on the top left hand section of the `Dining Philosophers' window, and the `Move() Counter Values' as displayed on the text-box on the right hand side of figure 6.9 are the same. This demonstrates that cost-of-service tracking variables can replace existing variables that are sparsely introduced for counting purposes.

Using Counter objects as described in section 5.3 helps to commit other tracking in a consistent manner, as well as using them for COST. Similar to the previous case-study, we observe again that association of counter variables with each method provides a frequency measure during requirements elicitation and specification generation. These measures can be scaled to provide realistic estimates for large scale software systems during design and implementation.

Readers and Writers

The readers-writers problem belong to the large class of classical concurrency-control problems that are often used for testing new and existing synchronisation schemes. The readers-writers problem was first discussed by Courtois et al. (1971). The issue of concurrent access to objects by readers and writers was further discussed by Lamport (1977). We develop a solution to the readers-writers problem in AsmL and C#, and introduce cost-of-service tracking measures in the AsmL specification. The COST counters that are inserted in the AsmL specification are used by the C# implementation to establish mutual exclusion and control concurrent access to a shared resource by multiple threads. First we define the `Reader' and `Writer' classes in AsmL, and then explain the synchronisation performed by the C# implementation in the following sections.

Reader and Writer Classes

Counter objects are declared in both the Reader and Writer classes for the Read() and Write() methods. The variable numberOfReaders in the Reader class keeps track of the number of readers that are in execution at a given instant. The difference between NBeg_Read and NEnd_Read gives us the number of readers currently in execution. The UpdateReaders() method is called after every counter increment or decrement to update the numberOfReaders variable. The Readers() method returns the numberOfReaders to the caller. The value of the NEnd_Read counter tells us the number of successful read operations that have been executed so far. The TotalReaders() method returns this value to the caller. Figure 6.10 shows the Reader class written in AsmL.

Figure 6.10: Reader Class in AsmL
\includegraphics[scale=0.8]{reader.eps}

The Writer class has corresponding methods similar to the Reader class for the above-mentioned purposes. Since we develop a solution where waiting writers are given preference over waiting readers, we define a WritersWaiting() method. The difference between the number of requests made to the Write() method, and the number of started executions of the Write() method gives us the number of writers that are waiting to access the shared resource. The WritersWaiting() method calculates the number of waiting writers and returns the value to the caller. Figure 6.11 shows the Writer class written in AsmL. Detailed source code listing of the Reader and Writer classes can be found in appendix C.1.

Figure 6.11: Writer Class Extract in AsmL
\includegraphics[scale=0.8]{writer.eps}

Synchronisation with Counters

An interface is developed in C# to spawn a number of threads that perform random read and write operations on a shared resource. Concurrent access is controlled by evaluating expressions in terms of the COST counters that are specified in the AsmL Reader and Writer classes. A random double between 0 and 1 is generated. If the generated random value is less than 0.8, then the current thread performs a read operation, otherwise it performs a write operation. In a realistic situation, it can be assumed that read operations are performed more frequently than write operations.

The BeginRead() method verifies if any writer threads are in execution and whether there are any threads waiting to write to the shared resource. The Writers() method and the WritersWaiting() method in the AsmL specification are used by the BeginRead() method for this purpose. The current thread waits for the writers to signal after they finish execution. We have similar begin and end methods for writers that wait and signal as appropriate by evaluating pre-conditions in terms of the COST counters defined in the AsmL specification. The total number of readers and writers that have finished execution are also incremented based on the COST counters. Figure 6.12 shows the user interface used to initialise and execute the threads, display the counters, and exit the program.

Figure 6.12: User Interface for Reader-Writer
\includegraphics[scale=0.8]{rwWindow.eps}

Observations

Similar to the dining philosophers problem case study in section 6.2.3, we observe the ease of using an AsmL specification in a concrete implementation developed in C#. Unlike the dining philosophers case study, we implement the synchronisation in the C# class instead of implementing it inside the AsmL specification. The AsmL specification defines the Counter, Reader and the Writer classes only. The C# implementation declares Reader and Writer objects. The threads synchronise by using the COST counters defined in AsmL specification. Figure 6.13 is an extract from an execution trace of the C# program where the same console is used to display outputs from both the C# implementation execution and the AsmL runtime execution.

Figure 6.13: Execution Trace of Readers-Writers Implementation
\includegraphics[]{rwExecTrace.eps}

The interoperability between AsmL specifications and corresponding implementations is evident from this case study. The ease of introducing cost-of-service tracking measures is also demonstrated. An existing dynamic link library can be refined to include COST counters by merely adding a Counter class and defining a corresponding abstract class with appropriate counter objects. The synchronisation developed as part of this case study in the C# implementation using COST counters defined in the AsmL specification also establishes the fact that assertions defined in an AsmL specification can be easily translated and used in a corresponding implementation. Figure 6.14 is a screen-shot of the program execution after the threads have performed random read and write operations on a shared resource, and have now stopped. The `Number of Reads' and the `Number of Writes' are displayed by the C# implementation, but the values are retrieved from the appropriate COST counters that are defined in the AsmL specification.

Figure 6.14: Display Counters
\includegraphics[]{rwEnd.eps}

From the observations made during this case study, we accentuate the theory that extra-functional properties can be tracked with considerable ease by introducing COST counters in an AsmL specification, and by using them in equivalent correct implementations. The ability to count the total number of read and write operations performed by using counters also demonstrates the ability to create a trace of history by using COST counters. A history trace can be used to implement bounded conditions to stop or start required executions once a counter reaches a pre-defined threshold. The successful tracking implemented in this case study also establishes that COST counters can be specified in both sequential and parallel system specifications.

AsmL Test Generator

The AsmL for Microsoft .NET distribution comes with an AsmL Test Generator. This test generator takes in specifications written in AsmL, input expressions and predicates. The test generator then generates parameters, call-sequences, and a finite state machine model. It also generates test sequences. The test generator was used to validate the models produced in the above case studies. An AsmL specification can be validated and refined by using the various features of the AsmL Test Generator. Defining COST attributes in a specification prior to validation helps in producing test sequences and cases that take the counters into account. The AsmL tester also provides a tool for conformance testing that performs runtime verification. Also known as `weaving', conformance testing allows the tester to run an AsmL model and the corresponding C# implementation in parallel. Time-constraints restrained us from using the `weaver' to its full potential to validate AsmL models and corresponding implementations written in .NET compliant languages.


A Proposal

Observations and results extracted from the conducted case studies led us to put forward the COST Proposal: to have built-in counters in AsmL. We propose a `cost' syntax that can be added to the AsmL library for cost-of-service tracking purposes. AsmL classes and methods can be tagged with a `cost' identifier as illustrated in figure 6.15.

Figure 6.15: Proposal: Cost Syntax Example
\includegraphics[scale=0.8]{cost.eps}

Once a class or a method has been tagged with a cost attribute, counters would be automatically declared and instantiated as required. In case of a class, all methods in the class will have counters that can be used for cost-of-service tracking. If it is desired that all methods of a class do not require associated COST counters barring one, then the individual method in question can be classified as a cost method.

The above mechanism should help in cost-of-service tracking of extra-functional, as well as functional properties in AsmL specifications, and can be further used in correct implementations written in any .NET aware programming language. The user is given full flexibility of tagging methods and classes that require tracking. It is a very simple and minimal proposal that can have far-reaching benefits in terms of reducing cost of software development, specially in the .NET environment. The object-oriented and abstraction properties of AsmL are also retained by using the counter interface and class. Specification of this proposal was out of the scope of this project, and can be an extensive undertaking for future projects.

Conclusions and Future Work

The Abstract State Machine (ASM) approach has been widely used for large-scale software specifications of realistic systems in several application domains in the recent past. Specifications based on a strong mathematical model have reduced cost and improved stability of software systems. Specification languages are being used to formalise the specification process, Microsoft AsmL being one such language.

This project adds a new dimension to ASM-based executable specifications by devising a way to track cost attributes of extra-functional properties in software systems. This opens up the prospect of specification, prediction and verification of extra-functional properties for large-scale software systems.

Work Done

Extra-functional properties and their influence on software systems can be difficult to isolate and track. This research project tried to bridge the gap between executable specifications and extra-functional properties by introducing a cost-of-service tracking measure. Associating such measures with executable specifications written in AsmL helps to estimate the cost of service incurred due to extra-functional properties in the specification phase.

Estimation of extra-functional properties during specification using the developed cost-of-service tracking measure reduces costs in various direct and indirect ways. For example, a real-time system, where high-speed performance is desired, might be able to use the estimated information to add more hardware to the system in the design phase to improve performance, as opposed to doing the same during the implementation or testing phase. Similarly, estimating response time for desktop programs might help to attract more users, or prevent loss of users due to slow response time.

An abstract model based on the theory of Abstract State Machines was developed to track cost-of-service as part of this research project. A Counter class and interface were designed and implemented in the case studies that were conducted. The Abstract State Machine Language was used for the case studies. The observations made from the case studies prove the effectiveness of this approach as a tracking measure. Different ways of associating the counters with different extra-functional properties were also illustrated as part of the case studies. Interoperability of this solution with the .NET framework makes it a viable approach to optimise a .NET framework based software system for extra-functional properties during specification phase.

Future Work


AsmL Pre-processor

We aimed at developing a pre-processor that would automate the process of introducing counters into AsmL specifications by pre-processing special comments. A particular syntax of commenting was devised for this purpose as shown in the marked boxes in figure 7.1.

Figure 7.1: Special Commenting Syntax for AsmL Pre-processor
\includegraphics[]{precode.eps}

As illustrated in figure 7.1, comments beginning with //@ will be parsed and replaced with appropriate `Begin' and `End' methods that would declare and initialise counters for the method. Optional assertions can be inserted in the comments inside square brackets. These assertions will also be inserted in the `Begin' and `End' methods as required. Such pre-processing would help to introduce counters, and establish program-wide invariants and assertions in terms of the `Begin' and `End' methods generated by the pre-processor. After pre-processing the code example in figure 7.1, the source code input for the AsmL compiler would be as shown in 7.2.

Figure 7.2: Pre-processed Code in AsmL
\includegraphics[]{postcode.eps}

Due to time-constraints and the complex nature of this undertaking, a basic pre-processor could not be developed as desired. Implementation of such a pre-processor can be done in future, and integrated with the .NET development environment. This is currently a work in progress, and can be further pursued as part of a PhD research project.

The COST Proposal

As detailed in section 6.5, we put forward a proposal to have built-in mechanisms for cost-of-service tracking in executable specifications written in AsmL. Detailed specification and implementation of this proposal would require modifications to the internal structure of AsmL, and hence is beyond the scope of this research project. Given the required resources and scope, the AsmL pre-processor as discussed in 7.2.1, and implementation of the COST proposal can be pursued in parallel.

Stack Specification Code


Reverse Polish Notation Specification

Counter Interface

Declares the counter interface
interface ICounter
  var counter as Integer = 0
  CounterValue() as Integer

  Increment()

  Decrement()

Counter Class

Defines the counter class
class Counter implements ICounter
  CounterValue() as Integer
    step
      return counter

  Increment()
    step
      counter := counter + 1

  Decrement()
    step
      counter := counter - 1

Stack Interface

Declares the stack interface
interface IStack
  // a stack of integers
  var s as Seq of Integer = []

  // Counter variables to count number of requests to 'push'es and 'pop's.
  // 'begin' and 'end' counters are not introduced as this is a trivial
  // example to illustrate the notion of counter variables.
  var NEnd_push = new Counter()
  var NEnd_pop = new Counter()
  var NEnd_top = new Counter()

  // Pushes an integer onto the stack
  Push(i as Integer)

  // Pops an integer from the stack
  // Requires a non-empty stack
  Pop()
    require s <> []

  // Returns the topmost member of the stack
  // Requires a non-empty stack
  Top() as Integer
    require s <> []

  // Displays the value of the counters
  DisplayCounters()

  constraint NEnd_push.CounterValue() >= NEnd_pop.CounterValue()

Stack Class

Defines the stack interface
class Stack implements IStack
  Push(i as Integer)
    step
      // pushes item onto the stack
      step 1: s := [i] + s
      // increases the 'end' counter
      step 2: NEnd_push.Increment()

  Pop()
    step
      // pops item from the stack
      step 1: s := Tail(s)
      // increases the 'end' counter
      step 2: NEnd_pop.Increment()

  Top() as Integer
    step
      // increases the 'request' counter
      step 1: NEnd_top.Increment()
      // returns topmost item from the stack
      step 2: return Head(s)

  DisplayCounters()
    step
      step 1: WriteLine("\n\t Number of calls to Push() : " 
                          + NEnd_push.CounterValue())
      step 2: WriteLine("\t Number of calls to Pop() : " 
                          + NEnd_pop.CounterValue())
      step 3: WriteLine("\t Number of calls to Top() : " 
                          + NEnd_top.CounterValue()  + "\n")

RPN Calculator Class

This is the Reverse Polish Calculator Class that implements the above interface.
interface ICalc
  Calculate()

class Calc implements ICalc
  Calculate()
    // Instantiate a new Stack
    var myStack = new Stack()

    // Declare and initialise counters
    var calcLoopCounter as Integer = 0
    var pushLoopCounter as Integer = 0
    // Declare and initialise current operator
    var current as Char = ' '
    // Declare and initialise arguments
    var arg1 as Integer = 0
    var arg2 as Integer = 0
    var stackElement = 0

    // Push 10 integers onto the Stack
    // Uses non-determinism to a certain extent
    step while pushLoopCounter < 10
      step stackElement := any x | x in {0..100}
      step myStack.Push(stackElement)
      step WriteLine("Pushing ... Top element after Push(): " 
                                             + myStack.Top())
      step pushLoopCounter := pushLoopCounter + 1

    step
      WriteLine("\n" + myStack.s) // Prints out stack

      // user input loop begins
      // The 'AssertionFailed' exception can be raised by iterating
      // the following loop 10 times (number of elements in the stack)
      step while calcLoopCounter < 9
        step WriteLine("\nEnter operator + - * / = or `ctrl+c' to quit")
        step current := ReadLine() as Char
        //step WriteLine(current)
        step
            if current = '+' then
              step
                step WriteLine("Stack : \t" + myStack.s)
                step WriteLine("Operator : \t" + current)
                step arg1 := myStack.Top()
                step myStack.Pop()
                step arg2 := myStack.Top()
                step myStack.Pop()
                step myStack.Push(arg1 + arg2)
                step WriteLine("Stack : \t" + myStack.s + "\n")
            else
              (if current = '-' then
                 step
                   step WriteLine("Stack : \t" + myStack.s)
                   step WriteLine("Operator : \t" + current)
                   step arg1 := myStack.Top()
                   step myStack.Pop()
                   step arg2 := myStack.Top()
                   step myStack.Pop()
                   step myStack.Push(arg1 - arg2)
                   step WriteLine("Stack : \t" + myStack.s + "\n")
               else
                 (if current = '*' then
                    step
                      step WriteLine("Stack : \t" + myStack.s)
                      step WriteLine("Operator : \t" + current)
                      step arg1 := myStack.Top()
                      step myStack.Pop()
                      step arg2 := myStack.Top()
                      step myStack.Pop()
                      step myStack.Push(arg1 * arg2)
                      step WriteLine("Stack : \t" + myStack.s + "\n")
                  else
                    (if current = '/' then
                       step
                         step WriteLine("Stack : \t" + myStack.s)
                         step WriteLine("Operator : \t" + current)
                         step arg1 := myStack.Top()
                         step myStack.Pop()
                         step arg2 := myStack.Top()
                         step myStack.Pop()
                         step myStack.Push(arg1 / arg2)
                         step WriteLine("Stack : \t" + myStack.s + "\n")
                     else
                       (if current = '=' then
                          step
                            step WriteLine("Stack : \t" + myStack.s)
                            step WriteLine("Operator : \t" + current)
                            step WriteLine("Result : \t" + myStack.Top())
                            step myStack.Pop()
                            step WriteLine("Stack : \t"+myStack.s+"\n")
                        else
                          step WriteLine("Invalid Input")
                        )
                     )
                  )
               )
        step calcLoopCounter := calcLoopCounter + 1
      // Display counter values at the end of execution
      step myStack.DisplayCounters()

Test Stub

A test stub that instantiates a Calc object and executes the Calculate() method.
[EntryPoint]
Main()
  var myCalc = new Calc()
  myCalc.Calculate()


Elementary Stack Testing Stub

[EntryPoint]
Main()
  // create stack
  var myStack = new Stack()

  if myStack.s = [] then
    WriteLine("Stack is Empty\n")
  else
    WriteLine("Stack not Empty\n")

  // Push integers onto the Stack
  // convert this to a 'foreach' loop maybe
  initially x = 1
  step while x < 6
    step myStack.Push(x)
    step WriteLine("Pushing ... Top element after Push(): "
                                             + myStack.Top())
    step x := x + 1

  step
    if myStack.s = [] then
      WriteLine("\nStack is Empty\n")
    else
      WriteLine("\nStack not Empty\n")

  // Pop integers from the Stack
  step
    initially y = 1
    step while y < 6
      step WriteLine("Top element before Pop(): "
                          + myStack.Top() + " Popping ...")
      step myStack.Pop()
      step y := y + 1

  step
    if myStack.s = [] then
      WriteLine("\nStack is Empty\n")
    else
      WriteLine("\nStack not Empty\n")
    myStack.Counters()

Dining Philosophers Code


AsmL Specification

This AsmL specification is a modified version of the `Dining Philosophers' solution provided as an example along with the AsmL for Microsoft .NET distribution. The lines of code that were added to the provided example are marked as follows:
// [Rupak Das]
Modified Code
// [/Rupak Das]

Namespace and Counters

The classes defined in this specification are a part of the `DiningPhilosophers' namespace. The counter interface and classes are added for cost-of-service tracking in the existing example specification.
namespace DiningPhilosophers

// [Rupak Das]
interface ICounter
  var counter as Integer = 0
  CounterValue() as Integer
  Increment()
  Decrement()

class Counter implements ICounter
  [EntryPoint]
  CounterValue() as Integer
    step
      return counter

  [EntryPoint]
  Increment()
    step
      counter := counter + 1

  [EntryPoint]
  Decrement()
    step
      counter := counter + 1
// [/Rupak Das]

Philosopher States

The philosopher cycles between the following states declared in the enum. The Fork structure is also defined.
// Defines the different states of philosophers
enum State
  Thinking
  Hungry
  HungryWithLeftFork
  Eating

structure Fork
  index as Integer

Abstract Philosopher class

// Abstract philosopher class
abstract class Philosopher
  var status as State = Thinking
  index as Integer
  // [Rupak Das]
  var NReq_canMove = new Counter()
  var NBeg_canMove = new Counter()
  var NEnd_canMove = new Counter()
  var NReq_move = new Counter()
  var NBeg_move = new Counter()
  var NEnd_move = new Counter()
  // [/Rupak Das]

  abstract canMove(table as Table) as Boolean
  abstract move(table as Table)
  // [Rupak Das]
  abstract displayCounters()
  // [/Rupak Das]

Other global variables and methods

numPhilosophers as Integer = 5
numForks as Integer = numPhilosophers
forks as Set of Fork = {Fork(i) | i in {1..numForks}}
// [Rupak Das]
var NReq_left = new Counter()
var NReq_right = new Counter()
// [/Rupak Das]

left(p as Philosopher) as Fork
  // [Rupak Das]
  // NReq_left.Increment()
  // WriteLine("Calls to left() by Philosopher " + p.index +
  //                ": " + NReq_left.CounterValue())
  // [/Rupak Das]
  return Fork(p.index)

right(p as Philosopher) as Fork
  // [Rupak Das]
  // NReq_right.Increment()
  // WriteLine("Calls to right() by Philosopher " + p.index +
  //                ": " + NReq_left.CounterValue())
  // [/Rupak Das]
  return Fork(p.index mod numPhilosophers + 1)

The `Table' class

class Table
  philosophers as Set of Philosopher
  var holder as Map of Fork to Philosopher = { -> }
  var fed as Set of Philosopher = {}
  var stepNo as Integer = 0
  // [Rupak Das]
  var NReq_Move = new Counter()
  var NBeg_Move = new Counter()
  var NEnd_Move = new Counter()
  // [/Rupak Das]

  [EntryPoint]
  Move()
    // [Rupak Das]
    NReq_Move.Increment()
    NBeg_Move.Increment()
    // [/Rupak Das]
    choose phil in philosophers where phil.canMove(me)
      phil.move(me)
      stepNo := stepNo + 1
    // [Rupak Das]
    NEnd_Move.Increment()
    // [/Rupak Das]

  [EntryPoint]
  shared InitGreedy() as Table
    philosophers = { new GreedyPhilosopher(i) as Philosopher |
                              i in [1..numPhilosophers] }
    return new Table(philosophers)

  // [Rupak Das]
  [EntryPoint]
  displayReqCounters() as String
    return NReq_Move.CounterValue().ToString()

  [EntryPoint]
  displayBegCounters() as String
    return NBeg_Move.CounterValue().ToString()

  [EntryPoint]
  displayEndCounters() as String
    return NEnd_Move.CounterValue().ToString()
  // [/Rupak Das]

  HoldsLeft(philIndex as Integer) as Boolean
    return exists (i,p) in holder where p.index = philIndex 
                                               and left(p) = i

  HoldsRight(philIndex as Integer) as Boolean
    return exists (i,p) in holder where p.index = philIndex 
                                              and right(p) = i

  IsFeeded(philIndex as Integer) as Boolean
    return exists p in fed where p.index = philIndex

  IsDeadlock() as Boolean
    return forall p in philosophers holds not p.canMove(me)

  IsGreedy() as Boolean
    return exists p in philosophers where p is GreedyPhilosopher

  StepNo() as Integer
    return stepNo

The `GreedyPhilosopher' class

class GreedyPhilosopher extends Philosopher
  override move(table as Table)
    // [Rupak Das]
    NReq_move.Increment()
    NBeg_move.Increment()
    // [/Rupak Das]
    match status
      Thinking : status := Hungry
      Hungry   : if not (left(me) in table.holder)
                   table.holder(left(me)) := me as Philosopher
                   status := HungryWithLeftFork
      HungryWithLeftFork
               : if not (right(me) in table.holder)
                   table.holder(right(me)) := me as Philosopher
                   status := Eating
                   add me to table.fed
      Eating   : remove table.holder(left(me))
                 remove table.holder(right(me))
                 status := Thinking
    // [Rupak Das]
    NEnd_move.Increment()
    displayCounters()
    // [/Rupak Das]

  override canMove(table as Table) as Boolean
    // [Rupak Das]
    NReq_canMove.Increment()
    NBeg_canMove.Increment()
    NEnd_canMove.Increment()
    // [/Rupak Das]
    return status = Thinking
      or (status = Hungry and left(me) notin table.holder)
      or (status = HungryWithLeftFork and right(me) notin table.holder)
      or status = Eating

  // [Rupak Das]
  override displayCounters()
    step WriteLine("Philosopher " + me.index + " has made "
                          + NEnd_move.CounterValue() + " moves")
  // [/Rupak Das]


C# Interface

This C# interface is a modified version of the `Dining Philosophers' solution provided as an example along with the AsmL for Microsoft .NET distribution. The lines of code that were added to the provided example are marked as follows:
// [Rupak Das]
Modified Code
// [/Rupak Das]

The `View' class

This class serves as a code-behind file for the graphical user interface.
//
// Foundations of Software Engineering
// Microsoft Research
// (c) Microsoft Corporation. All rights reserved.
//
// Modified by Rupak Das for research purposes
// Dated: 20th October, 2003
//
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace DiningPhilosophers
{
    /// <summary>
    /// Summary description for View.    
    /// </summary>
    public class View : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Label Phi1;
        private System.Windows.Forms.Label Phi3;
        private System.Windows.Forms.Label Phi2;
        private System.Windows.Forms.Label Phi4;
        private System.Windows.Forms.Label Phi5;
        private System.Windows.Forms.Button Run;
        private System.Windows.Forms.Button Quit;
        private System.Windows.Forms.Label Counter;

        private System.Windows.Forms.Label Fork1l;
        private System.Windows.Forms.Label Fork1r;
        private System.Windows.Forms.Label Fork2l;
        private System.Windows.Forms.Label Fork2r;
        private System.Windows.Forms.Label Fork3l;
        private System.Windows.Forms.Label Fork3r;
        private System.Windows.Forms.Label Fork4l;
        private System.Windows.Forms.Label Fork4r;
        private System.Windows.Forms.Label Fork5l;
        private System.Windows.Forms.Label Fork5r;
        private System.Windows.Forms.Button Greedy;

        private System.Windows.Forms.Label[] Phils;

        private System.Windows.Forms.Label[] Forks;

        private System.Windows.Forms.Button Step;
      
        private Table table;
		
        // [Rupak Das]
        private System.Windows.Forms.Button displayCounterBtn;
        private System.Windows.Forms.TextBox counterTxt;
        // [/Rupak Das]

        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;

        public View()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

            Phils = new System.Windows.Forms.Label[]{Phi1,Phi2,Phi3,
                                                         Phi4,Phi5};
            Forks = new System.Windows.Forms.Label[]{Fork1r,Fork1l,
                                                     Fork2r,Fork2l,
                                                     Fork3r,Fork3l,
                                                     Fork4r,Fork4l,
                                                     Fork5r,Fork5l};

            Step.Click += new EventHandler(OnStep);
            Run.Click  += new EventHandler(OnRun);
            Quit.Click += new EventHandler(OnQuit);
            Greedy.Click += new EventHandler(OnGreedy);
            // [Rupak Das]
            // Generous.Click += new EventHandler(OnGenerous);
            // [/Rupak Das]

            table = Table.InitGreedy();
            Redraw(); 
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }   

        // The windows form designer generated code 
        // was left out of this listing due to page-limit
        // constraints.
        #region Windows Form Designer generated code
        #endregion

        void Redraw()
        {
            for (int i = 1; i <= 5; i++)
            {
                Forks[(i-1)*2].Visible = table.HoldsLeft(i);
                Forks[(i-1)*2+1].Visible = table.HoldsRight(i);
                if (table.IsFeeded(i))
                {
                    Phils[i-1].BackColor = Color.Green;
                } 
                else 
                {
                    Phils[i-1].BackColor = Color.Yellow;
                }
            }

            // [Rupak Das]
            Counter.Text = (table.IsGreedy() ? "Step #" : 
                    "generous step #") + table.StepNo() 
                    + (table.IsDeadlock() ? " results in deadlock." : "");
            if(table.IsDeadlock())
            {
                Console.WriteLine("DeadLock");
            }
            // [/Rupak Das]
        }
        
        void OnStep(object o,System.EventArgs a)
        {
            table.Move();
            Redraw();
        }

        void OnRun(object o,System.EventArgs a)
        {
            int max = 5000;
            while (!table.IsDeadlock() && max-- > 0)
            {
                OnStep(o,a);
                this.Update();
            }
            Redraw();
            Counter.Text += ", stopping.";
            Counter.Update();
        }

        void OnQuit(object o,System.EventArgs a)
        {
            Application.Exit();
        }
            
        void OnGreedy(object o,System.EventArgs a)
        {
            table = Table.InitGreedy();
            Redraw();
        }

        // [Rupak Das]
        /*void OnGenerous(object o,System.EventArgs a)
        {
            table = Table.InitGenerous();
            Redraw();
        }*/
        // [/Rupak Das]

        [STAThread]
        static void Main() 
        {
            Application.Run(new View());
        }

        // [Rupak Das]
        private void displayCounterBtn_Click(object sender, 
                                         System.EventArgs e)
        {
            counterTxt.AppendText("\r\n\r\n");
            counterTxt.AppendText(" NReq_Move: ");
            counterTxt.Text += table.displayReqCounters();
            counterTxt.Text += "\r\n NBeg_Move: ";
            counterTxt.Text += table.displayBegCounters();
            counterTxt.Text += "\r\n NEnd_Move: ";
            counterTxt.Text += table.displayEndCounters();
        }
        // [/Rupak Das]		
    }
}

Reader-Writer code


AsmL Reader and Writer class

Counter Interface and Class

Defines the counter interface and class.
namespace ReaderWriter

interface ICounter
  var counter as Integer = 0
  CounterValue() as Integer
  Increment()
  Decrement()

class Counter implements ICounter
  CounterValue() as Integer
    step
      return counter
  Increment()
    step
      counter := counter + 1
  Decrement()
    step
      counter := counter - 1

The Reader Class

Defines the Reader class.
[EntryPoint]
public class Reader
  var NReq_Read = new Counter()
  var NBeg_Read = new Counter()
  var NEnd_Read = new Counter()
  var numberOfReaders as Integer = 0

  [EntryPoint]
  BegRead()
    NReq_Read.Increment()
    NBeg_Read.Increment()
    UpdateReaders()

  [EntryPoint]
  Read()
    BegRead()
    // An actual read operation is not
    // performed as the aim of this task
    // was to implement synchronisation,
    // and not performing file I/O
    WriteLine("Reading ...")
    EndRead()

  [EntryPoint]
  EndRead()
    NEnd_Read.Increment()
    UpdateReaders()

  [EntryPoint]
  UpdateReaders()
    numberOfReaders = NBeg_Read.CounterValue()
                       - NEnd_Read.CounterValue()

  [EntryPoint]
  Readers() as Integer
    step
      return numberOfReaders

  [EntryPoint]
  TotalReaders() as Integer
    step
      return NEnd_Read.CounterValue()

The Writer Class

Defines the Writer class.
[EntryPoint]
public class Writer
  var NReq_Write = new Counter()
  var NBeg_Write = new Counter()
  var NEnd_Write = new Counter()
  var numberOfWriters as Integer = 0

  [EntryPoint]
  BegWrite()
    NReq_Write.Increment()

  [EntryPoint]
  Write()
    NBeg_Write.Increment()
    UpdateWriters()
    // An actual write operation is not
    // performed as the aim of this task
    // was to implement synchronisation,
    // and not performing file I/O
    WriteLine("Writing ...")
    EndWrite()

  [EntryPoint]
  EndWrite()
    NEnd_Write.Increment()
    UpdateWriters()

  [EntryPoint]
  UpdateWriters()
    numberOfWriters = NBeg_Write.CounterValue()
                       - NEnd_Write.CounterValue()

  [EntryPoint]
  Writers() as Integer
    step
      return numberOfWriters

  [EntryPoint]
  WritersWaiting() as Integer
    step
      return NReq_Write.CounterValue()
                       - NBeg_Write.CounterValue()

  [EntryPoint]
  TotalWriters() as Integer
    step
      return NEnd_Write.CounterValue()


C# Threading and Synchronisation

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;

namespace ReaderWriter
{
    /// <summary>
    /// Summary description for ReadWrite.
    /// </summary>
    public class ReadWrite : System.Windows.Forms.Form
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.Container components = null;
        Reader myReader = new Reader();
        Writer myWriter = new Writer();
        AutoResetEvent autoEvent = new AutoResetEvent(false);
        const int numThreads = 26;
        public static bool running = true;
        private System.Windows.Forms.Button InitialiseBtn;
        private System.Windows.Forms.TextBox statusBox;
        private System.Windows.Forms.Button counterBtn;
        private System.Windows.Forms.Label readLbl;
        private System.Windows.Forms.Label writeLbl;
        private System.Windows.Forms.Button exitBtn;
        private static Random rnd = new Random();
        private int totalReads = 0;
        private int totalWrites = 0;


        public ReadWrite()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();            
        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if(components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }

        // The windows form designer generated code
        // was left out of this listing due to page-limit
        // constraints.                        
        #region Windows Form Designer generated code
        #endregion

        public void BeginRead()
        {
            try
            {
                // require Writers() eq 1 and WritersWaiting eq 0
                while (myWriter.Writers() != 1 && 
                                  myWriter.WritersWaiting() != 0)
                {
                    Console.WriteLine("... Waiting to Read ...");
                    autoEvent.WaitOne();
                }                
                myReader.Read();
                Thread.Sleep(100);                
                //statusBox.Text += "\r\nReading ...";
                EndRead();
            }
            catch
            {                
            }
        }        

        public void EndRead()
        {
            Console.WriteLine("Signalling Writers ...");
            autoEvent.Set();
        }

        public void BeginWrite()
        {
            myWriter.BegWrite();

            try 
            {
                // require Readers() eq 0
                while (myReader.Readers() != 0)
                {
                    Console.WriteLine("... Waiting to Write ...");
                    autoEvent.WaitOne();
                }
                myWriter.Write();
                Thread.Sleep(500);
                //statusBox.Text += "\r\nWriting ...";
                EndWrite();
            }
            catch
            {}
        }

        public void EndWrite()
        {
            if (myWriter.WritersWaiting() == 0)
            {
                Console.WriteLine("Signalling Readers ...");
                autoEvent.Set();
            }
        }        

        public void ThreadProc()
        {
            while (running)
            {
                double action = rnd.NextDouble();
                if (action < 0.8)
                {
                    //statusBox.Text += "\r\nReading ...";
                    BeginRead();
                }
                else
                {
                    //statusBox.Text += "\r\nWriting ...";
                    BeginWrite();
                }
            }
        }

        private void InitialiseBtn_Click(object sender, 
                                        System.EventArgs e)
        {
            readLbl.Text = "Number of Reads:";
            writeLbl.Text = "Number of Writes:";
            // Start a series of threads.
            // Each thread randomly performs reads and writes on
            // shared resources.
            statusBox.Text = "Status:\r\nInitialising ...";
            
            Thread[] t = new Thread[numThreads];
            for (int i = 0; i < numThreads; i++)
            {
                t[i] = new Thread(new ThreadStart(ThreadProc));
                t[i].Name = new string(Convert.ToChar(i + 65), 1);
                statusBox.Text += "\r\nStarting thread " 
                                     + t[i].Name.ToString();
                t[i].Start();

                if (i > 10)
                {
                    Thread.Sleep(1500);
                }
            }

            // Shut down all threads
            running = false;
            for (int i = 0; i < numThreads; i++)
            {
                totalReads += myReader.TotalReaders();
                totalWrites += myWriter.TotalWriters();

                Console.WriteLine("Total Reads by Thread " 
                    + t[i].Name.ToString()
                    + ":\t {0}", myReader.TotalReaders());
                Console.WriteLine("Total Writes by Thread " 
                    + t[i].Name.ToString() 
                    + ":\t {0}", myWriter.TotalWriters());*/
                
                //autoEvent.Set();
                //t[i].Join();                
                t[i].Join(30);
            }

            Console.WriteLine("\r\n{0} reads and {1} writes executed.", 
                totalReads, totalWrites);                
            Console.WriteLine("THE END");            
        }

        private void counterBtn_Click(object sender, System.EventArgs e)
        {
            readLbl.Text = "Number of Reads:\r\n" + totalReads;
            writeLbl.Text = "Number of Writes:\r\n" + totalWrites;
        }        

        [STAThread]
        static void Main()
        {
            Application.Run(new ReadWrite());
        }

        private void exitBtn_Click(object sender, System.EventArgs e)
        {
            Application.Exit();
        }
    }
}

Bibliography

Anlauff, M. (2000).

XASM - An Extensible, Component-Based Abstract State Machines Language, in Y. Gurevich, P. W. Kutter, M. Odersky and L. Thiele (eds), Proceedings of the Abstract State Machines conference (ASM 2000), Vol. 1912 of Lecture Notes in Computer Science, Springer-Verlag, pp. 69-90.
URL: http://www.xasm.org/

Barnett, M., Börger, E., Gurevich, Y., Schulte, W. and Veanes, M. (2000).

Using Abstract State Machines at Microsoft: A Case Study, in Y. Gurevich, P. W. Kutter, M. Odersky and L. Thiele (eds), Proceedings of the Abstract State Machines conference (ASM 2000), Vol. 1912 of Lecture Notes in Computer Science, Springer-Verlag, pp. 367-379.

Barnett, M., Campbell, C., Schulte, W. and Vanes, M. ( 2001).

Specification, Simulation and Testing of COM Components using Abstract State Machines, Proceedings of the Abstract State Machines conference (ASM 2001).

Barnett, M. and Schulte, W. (2001a).

Spying on Components: A Runtime Verification Technique, Proceedings of the Workshop on Specification and Verification of Component-based Systems OOPSLA 2001.

Barnett, M. and Schulte, W. (2001b).

The ABCs of Specification: AsmL, Behavior, and Components, Informatica 25(4): 77-111.

Barnett, M. and Schulte, W. (2002).

Contracts, Components, and their Runtime Verification on the .NET Platform, Technical Report MSR-TR-2002-38, Microsoft Research.

Börger, E. (1990a).

A Logical Operational Semantics for Full Prolog. Part I: Selection Core and Control, in E. Börger, H. K. Büning and M. M. Richter (eds), CSL'89, 3rd Workshop on Computer Science Logic, Vol. 440 of Lecture Notes in Computer Science, Springer-Verlag, pp. 36-64.

Börger, E. (1990b).

A Logical Operational Semantics for Full Prolog. Part II: Built-in Predicates for Database Manipulations, in B. Rovan (ed.), In Proceedings of Mathematical Foundations of Computer Science, Vol. 452 of Lecture Notes in Computer Science, Springer-Verlag, pp. 1-14.

Börger, E. (1995).

Why Use Evolving Algebras for Hardware and Software Engineering?, in M. Bartosek, J. Staudek and J. Wiedermann (eds), SOFSEM '95: Theory and Practice of Informatics, Vol. 1012 of Lecture Notes in Computer Science, Springer-Verlag, pp. 236-271.

Börger, E. (1999).

High Level System Design and Analysis using Abstract State Machines, in D. Hutter, W. Stephan, P. Traverso and M. Ullman (eds), Current Trends in Applied Formal Methods (FM-Trends 98), Vol. 1641 of Lecture Notes in Computer Science, Springer-Verlag, pp. 1-43.

Börger, E. (2000).

Abstract State Machines at the Cusp of the Millenium, in Y. Gurevich, P. W. Kutter, M. Odersky and L. Thiele (eds), Proceedings of the Abstract State Machines conference (ASM 2000), Vol. 1912 of Lecture Notes in Computer Science, Springer-Verlag, pp. 1-8.

Börger, E., Päppinghaus, P. and Schmid, J. ( 2000).

Report on a Practical Application of ASMs in Software Design, in Y. Gurevich, P. W. Kutter, M. Odersky and L. Thiele (eds), Proceedings of the Abstract State Machines conference (ASM 2000), Vol. 1912 of Lecture Notes in Computer Science, Springer-Verlag, pp. 361-366.

Botella, P., Burgués, X., Franch, X., Huerta, M. and Salazar, G. (2001).

Modeling Non-Functional Requirements, Proceedings of Jornadas de Ingeniería de Requisitos Aplicada JIRA 2001, Sevilla.

Courtois, P. J., Heymans, F. and Parnas, D. L. ( 1971).

Concurrent Control with `Readers' and `Writers', Communications of the ACM 14(10): 667-668.

Del Castillo, G. (1998).

The ASM Workbench: an Open and Extensible Tool Environment for Abstract State Machines, Proceedings of the 28th Annual Conference of the German Society of Computer Science, Technical Report, Magdeburg University.

Dijkstra, E. W. (1972).

Hierarchical Ordering of Sequential Processes, in C. A. R. Hoare and R. H. Perrot (eds), Operating Systems Techniques, Academic Press, London, pp. 72-93.

Foundations of Software Engineering (2003a)
.
Microsoft Research Foundations of Software Engineering website.
URL: http://research.microsoft.com/fse/

Foundations of Software Engineering (2003b)
.
Microsoft Research AsmL website.
URL: http://research.microsoft.com/foundations/AsmL/

Foundations of Software Engineering (2003c)
.
Stack: An Example for Test Sequence Generation and Conformance Testing with AsmL, Microsoft Corporation, AsmL specification accompanying AsmL for .NET toolkit.

Franch, X. (1997).

The Convenience for a Notation to Express Non-Functional Characteristics of Software Components, in G. T. Leavens and M. Sitaraman (eds), Proceedings of the First Workshop on the Foundations of Component-Based Systems, Zurich, Switzerland, September 26 1997, pp. 101-110.

Franch, X. and Botella, P. (1996).

Putting Non-Functional Requirements into Software Architecture, Proceedings of the 9th International Workshop on Software Specification and Design, Ise-Shima, Japan, IEEE Computer Society, pp. 60-67.

Franch, X. and Botella, P. (1997).

Supporting Software Maintenance with Non-Functional Information, Proceedings of 1st EUROMICRO Conference on Software Maintenance and Reengineering, Berlin, Germany, IEEE Computer Society, pp. 10-16.

Glässer, U., Gurevich, Y. and Veanes, M. ( 2001).

Universal Plug and Play Machine Models, Technical Report MSR-TR-2001-59, Microsoft Research.

Gordon, A. D. and Syme, D. (2001).

Typing a Multi-Language Intermediate Code, ACM SIGPLAN Notices 36(3): 248-260.

Gurevich, Y. (1985).

A New Thesis, Abstracts, American Mathematical Society 6(4): 317.

Gurevich, Y. (1998).

Logic and the Challenge of Computer Science, in E. Börger (ed.), Current Trends in Theoretical Computer Science, Computer Science Press, pp. 1-57.

Gurevich, Y. (1999).

The Sequential ASM Thesis, Bulletin of the European Association for Theoretical Computer Science 67: 93-124.

Gurevich, Y. (2001).

Logician in the land of OS: Abstract State Machines at Microsoft, Proceedings of the Sixteenth Annual IEEE Symposium on Logic in Computer Science, IEEE Computer Society Press, pp. 129-136.

Gurevich, Y., Schulte, W. and Veanes, M. ( 2001).

Rich Sequential-Time ASMs, Proceedings of the Abstract State Machine conference (ASM 2001).

Huggins, J. (2003).

Michigan University website on Abstract State Machines.
URL: http://www.eecs.umich.edu/gasm/

Issarny, V., Bidan, C., Leleu, F. and Saridakis, T. ( 1997).

Towards Specifying QoS-Enabling Software Architectures, Proceedings of the 5 th International Workshop on Quality of Service (IWQOS'97), Columbia University, New York, USA, pp. 363-366.

Kleymann, T. (1999).

Hoare Logic and Auxiliary Variables, Formal Aspects of Computing 11(5): 541-566.

Lamport, L. (1977).

Concurrent Reading and Writing, Communications of the ACM 20(11): 806-811.

Landes, D. and Studer, R. (1995).

The Treatment of Non-Functional Requirements in MIKE, Proceedings of the 5th European Software Engineering Conference (ESEC), Barcelona (Catalunya, Spain), Vol. 989 of Lecture Notes in Computer Science, Springer-Verlag.

Lau, K.-K. (2001).

Component Certification and System Prediction: Is there a Role for Formality?, in I. Crnkovic, H. Schmidt, J. Stafford and K. Wallnau (eds), Proceedings of the 4th ICSE Workshop on Component-Based Software Engineering (ICSE CBSE4).

Microsoft Corporation (2002).

Microsoft Corporation COM website.
URL: http://www.microsoft.com/com/default.asp

Microsoft Corporation (2003).

Microsoft Corporation .NET website.
URL: http://www.microsoft.com/net/

Modeled Computation LLC (2001).

Executable Specifications: Creating Testable, Enforceable Designs, Technical report, Modeled Computation LLC, 4341-1/2 University Way, Seattle, WA 98105-5808, USA, http://www.modeled-computation.com.

Modeled Computation LLC for Microsoft ( 2002a).

AsmL: The Abstract State Machine Language, first edn.

Modeled Computation LLC for Microsoft ( 2002b).

Introducing AsmL: A Tutorial for the Abstract State Machine Language, second edn.

Mylopoulos, J., Chung, L. and Nixon, B. ( 1992).

Representing and Using Nonfunctional Requirements: A Process-Oriented Approach, IEEE Transactions on Software Engineering 18(6).

Salazar-Zárate, G., Botella, P. and Dahanajake, A. (2002).

An Approach to Deal with Non-Functional Requirements within UML, Proceedings of the Information Resources Management Association International Conference. IRMA2002. Seattle, USA, IRM Press.

Schmid, J. (2001).

AsmGofer website.
URL: http://www.tydo.de/AsmGofer/

Schmidt, H. (2001).

Trusted Components - Towards Automated Assembly with Predictable Properties, in I. Crnkovic, H. Schmidt, J. Stafford and K. Wallnau (eds), Proceedings of the 4th ICSE Workshop on Component-Based Software Engineering (ICSE CBSE4).

Schmidt, H. and Zimmermann, W. (1994)
.
A Complexity Calculus for Object-Oriented Programs, Object-Oriented Systems 1(2): 117-148.

Sommerville, I. (1995).

Software Engineering, fifth edn, Addison-Wesley Publishing Company.

Universitat Politécnica de Catalunya ( 2003).

GESSI Research group website.
URL: http://www.lsi.upc.es/~gessi/

Vieira, M. E. R., Dias, M. S. and Richardson, D. J. ( 2001).

Describing Dependencies in Component Access Points, in I. Crnkovic, H. Schmidt, J. Stafford and K. Wallnau (eds), Proceedings of the 4th ICSE Workshop on Component-Based Software Engineering (ICSE CBSE4).

About this document ...

This document was generated using the LaTeX2HTML translator Version 2K.1beta (1.48)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -split 0 -dir html -t COST:Cost-of-Service thesis04Nov.tex

The translation was initiated by MR RUPAK DAS on 2003-11-13


next_inactive up previous
MR RUPAK DAS 2003-11-13