Storage Informer
Storage Informer

Stateful Programming – A Case Study

by on Jul.27, 2009, under Storage

Stateful Programming – A Case Study

One of the basic tools that a programmer has in multi-core programming and parallel computing is the state maintainability. A serial application has only one flow and therefore the Call-Stack (list of nested function calls) is in a way the application&aposs state. In a parallel environment this is clearly not the case because there are many threads with many Call-Stacks at the same time. For example taking a snap shot of a parallel system in order to reproduce a bug requires the states of all running threads, sometimes processes, and sometimes even the operating system. The operating system behaves differently when it has enough memory than when it is out of memory. We need a complete system snap-shot in order to reproduce and solve bugs. You can read more about this in my previous post here: Stateful Programming – a key element.

There are three basic types of Runtime States that we consider:
1. First is the state of the operation I am working on right now: this thread, this object, this task, etc.
2. There is the collection of states of all other operations currently running in the system: other threads, other objects, other processes, etc.
3. There is also the state of the entire system: out of memory, flooded disk queue, with garbage collection in the background, etc.

When a program is running and I don&apost know its state I have no way of knowing what went wrong. The more stateful the application the more I know what is going on with it. Knowing the current state of operation can help me in two ways:
1. My current state: meaning know what is the last thing my application has performed and how well it is performing, and
2. Overall state: meaning learn the state of the system around me by the way my code is operating. For example if I try to allocate memory and get a response of &aposout of memory&apos then it is probable that my other module had crashed because one of the ActiveX controls it was operating crashed because the system is out of memory.

There is a class of students that I am teaching these days. It is a 3 months programming course and they start with C, go over C++ and then C#. In the way they are taught the many concepts of programming such as parallel computing, embedded CE and VX Works, system design, etc.

My part started last week with a course about software debugging and bug prevention. This monday we start parallel computing. This is before they know Object Oriented and C++ programming and it is for a very good reason. We want to see if it helps to understand the parallel system flow before the mind is sealed with objects and the methodology around it.

This time when I went over the debugging slides in class I deviated at times. The goal was to focus on debugging techniques that would be also helpful in the parallel world. This worked like magic. It so seem that the techniques of the parallel world reduced debugging complexity for a serial application as well.

My focus here is on the stateful programming aspect of debugging. Far too often the only way to find a flow-bug in a parallel system is to look it up in the application&aposs design. For this reason Stateful Programming has to do with design as much as it has to do with programming. We take a simple application that opens a file appends "1234" to it and closes the file. The file name is provided by the user. Here is the stateful analysis of the application:

Generally speaking we say that every time a decision is made in the code we change state. For example if I try to open a file and the file is opened then the applciation moved from a state of "need to open file" to "file is ready for work". If file opening failed then the application moved from "need to open a file" to "the file cannot be opened" which means that the overall operation fails. This means that whenever there is an &aposif&apos statement we change a state. We then add that when ever there is a function call that can return a value other than success this function call is a state shifter. The API call to open a file can return either the file is opened or not so this call is supposed to change the state of the application.

This is generally speaking. More practically speaking we say that everytime there is an error it has to be made noticable either by breaking the application or posting a message to a log, to the user, or any other method. We also say thet there are hirarchies for states so unless I am trying to debug the user input loop (asking for a file name) I don&apost really care whether it failed and is asking the user again for the input, all I care is the final output of this loop: either we got the input or we don&apost.

We can of course specify macro flags to enable and disable message for internal states (to be tested using #ifdef). The power of logging states is that when an application crashes or has some race condition we can determin what happened because we have a good snapshot of the application and what it was doing. It is possible for example to see in the log that one thread was working with a file at the same time that another thread already was.
Stateful Programming comes from the design and we need at least part of the Flow Diagram for our system. The best way to follow this through is to have a Flow Diagram followed by an Object Block Diagram, followed by level 2 Flow Diagram for internal followed by an Object Block Diagram and so on…

See the following diagram:

(Stateful Programming)

Here is a list of states according to this diagram:
* Starting
* Getting User Input
* Exiting: User Request
* Opening File "C:\my file"
* Writing To File 4 bytes to "C:\my file"
* Notifying User Of Error in File Write
* Closing File
* Process Completed Successfully

Here is a list of error states according to the diagram:
* Error Getting User Input
* Error Opening File "C:\my file"
* Error Writing To File: 4 bytes to "C:\my file"

Some of the state notifications could be hidden unless activated. The user input loop can also have a few internal states activated on demand.

When we have several threads and processes running in parallel it is relatively simple to track down flow bugs in the system. On any given time the collection of states of all threads is the state of the appliation. Now flow control bugs (A.K.A. "Random Bugs") are very predictable.
This is also compatible with sequence diagrams in visual studio 2010.


:, , , , ,

Leave a Reply

Powered by WP Hashcash

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...