Software Architecture and Larger System Design Issues Lecture 6: Advanced state modeling/analysis

Preview:

DESCRIPTION

Software Architecture and Larger System Design Issues Lecture 6: Advanced state modeling/analysis. Topics: Modeling/analyzing concurrent behaviors using UML state diagrams Chapter 6 in Blaha and Rumbaugh Additional topics not in the Blaha/Rumbaugh book. Outline of course topics. - PowerPoint PPT Presentation

Citation preview

E. KraemerCSE 335: Software Design

Software Architecture and Larger System Design Issues

Lecture 6: Advanced state modeling/analysis

Topics:– Modeling/analyzing concurrent behaviors using UML

state diagrams– Chapter 6 in Blaha and Rumbaugh– Additional topics not in the Blaha/Rumbaugh book

E. KraemerCSE 335: Software Design

Outline of course topicsFoundational OO concepts

Synthetic concepts

Software architecture and larger design issues:– Strategic design decisions that influence a host of smaller, more tactical

design decisions• E.g., policy for persistence of data in long-running system• E.g., allocating functionality to a single, centralized system vs. distributing

functionality among a collection of communicating hosts– Often involve a major capital investment– Source of both risk and opportunity– Require lots of a priori modeling and analysis– Focus: Design issues related to concurrent and distributed systems

Software process issues

E. KraemerCSE 335: Software Design

Analytical models of behaviorThus far, the models we have employed have proved

useful for– documentation/explanation– “roughing out” a design prior to implementation

Still, they are not very rigorous:– E.g., sequence diagrams depict only one scenario of

interaction among objects– Not good for reasoning about space of possible behaviors

Such reasoning requires more formal and complete models of behavior

E. KraemerCSE 335: Software Design

State diagrams

Useful for modeling “space of behaviors” of an object or a system of interacting objects

Requires:– Identifying and naming the conceptual “states” that an

object might be in, and– Conceivable transitions among those states and the

events (and/or conditions) that trigger (and/or guard) these transitions

Concurrent compositions of state diagrams can be “executed” to expose anomalous behaviors

E. KraemerCSE 335: Software Design

Communication among concurrent state machines

More interesting applications involve interaction (explicit communication) among state machines

Examples:– Active client objects interacting with a shared queue– Sensor object notifying a software controller– Perhaps even an object invoking a method on

anotherUML provides send actions by which one machine

may signal another

E. KraemerCSE 335: Software Design

Simple example: Client using a queue

q : Queuec1 : Client

System comprises two objectsEach object modeled by a state machineSystem state at any time is the pair (state of c1, state of q)

E. KraemerCSE 335: Software Design

Modeling method invocations

Given state machines for two objects C and S, where C is the client and S the supplier of a method m

Model call and return of m as separate signals

C sends the call signal to S and then enters a waiting state, which is exited upon reception of a return signal from S

E. KraemerCSE 335: Software Design

Example

Waiting... / send S.mCall(this, ...) mRet(...)

ProcessingBody of M

... / send caller.mRet(...)mCall(caller, ...)

Client

Supplier

E. KraemerCSE 335: Software Design

Exercise

Develop state models for a simple client and a queue, assuming:– class Client does nothing but repeatedly pull items

off of the queue– class Queue provides an operation pull, which is

implemented by calling empty, back, and pop on a private data member of type queue<string>

E. KraemerCSE 335: Software Design

Example: Client model

do / processString(b,s)

/ send q.pullCall(this) WaitingInitializing

pullReturn(b,s)

Client

E. KraemerCSE 335: Software Design

Example: Shared queue

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

Queue

E. KraemerCSE 335: Software Design

Recall: Two active clients sharing a queue

q : Queue

c1 : Client c2 : Client

q q

E. KraemerCSE 335: Software Design

Question

Do our state diagrams for classes Client and Queue accurately model the behaviors of active clients acting on a shared queue?

E. KraemerCSE 335: Software Design

Question

Do our state diagrams for classes Client and Queue accurately model the behaviors of active clients acting on a shared queue?

Answer really depends upon the “semantics” of event handling among concurrent state machines

E. KraemerCSE 335: Software Design

Semantics of parallel composition

Multiple interpretations:– Concurrent regions execute independently

• What happens if transitions in different regions are triggered by same event?

• Do both execute simultaneously? Does one “consume” the event to the exclusion of the other? Does each get a separate “copy” of the event?

– Concurrent regions communicate with one another, synchronizing on common events• Regions can only proceed when all are ready to proceed• Regions transfer data values during a concurrent transition

– Do we distinguish internal and external events?

E. KraemerCSE 335: Software Design

UML 2.0 Interpretation: Asynchronous events run to completion

Run-to-completion semantics:– State machine processes one event at a time and

finishes all consequences of that event before processing another event

– Events do not interact with one another during processing

Event pool:– Where new events for an object are stored until object

is ready to process them– No event ordering assumed in the pool

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

c1’s pool: c2’s pool:

q’s pool:Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

c1’s pool: c2’s pool:

q’s pool:Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

c1’s pool: c2’s pool:

q’s pool:Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

q’s pool: pullCall(c1)

c1’s pool: c2’s pool:

Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

q’s pool:

c2’s pool:c1’s pool:

Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

q’s pool: pullCall(c2)

c2’s pool:c1’s pool:

Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

q’s pool: pullCall(c2)

c2’s pool:c1’s pool:

Queue

E. KraemerCSE 335: Software Design

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(false,empty)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmpty do / s := q.back

[q.empty()]

[!q.empty()]

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

do / processString(b,s)

/ send q.pullCall(this)

WaitingInitializing

pullReturn(b,s)

Client

c1’s pool: pullRet(false, empty)

q’s pool: pullCall(c2)

c2’s pool:

Queue

E. KraemerCSE 335: Software Design

Observations

Modeling method invocations as asynchronous events which are placed in a pool:– Requests for service on an object:

• “buffered up” on arrival• dispatched when the object is ready to handle them

– Natural interpretation for how an active object can be invoked

– Makes passive objects appear to execute with “monitor semantics”

E. KraemerCSE 335: Software Design

Observations (continued)

In real programs, not every passive object is (or should be) a monitor:– There is some expense associated with acquiring

more locks than are needed to synchronize threads– We often want to analyze a system to choose which

passive objects should be monitors.

How could we use state-machine models for this purpose?

E. KraemerCSE 335: Software Design

More precisely…

How could we model the shared queue as a state machine that admits the behaviors on the following slide?

E. KraemerCSE 335: Software Design

Example

q :Queue c2 : …c1 : …

pull

empty

back

pop

pull

empty

back

pop

E. KraemerCSE 335: Software Design

Answer

Duplicate an object’s state model with one copy for each system thread

Note: This will need to be done for each passive object, and it will potentially cause the number of states in the system to grow out of control

E. KraemerCSE 335: Software Design

Example: Shared queue

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

Initial state of shared queue

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

Client c1 invokes pull…

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

Queue is not empty…

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

At this point, context switch and client c2 invokes pull…

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

C1 has yet to pop queue; so c2’s check for empty fails

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

Bad state! If queue contained only one element…

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

Idle

ProcessingPullCall

Checking

/ send caller.pullRet(…)

/ send caller.pullRet(true,s)

pullCall(caller)

Empty

NotEmptydo / s := q.back

[q.empty()]

[!q.empty()]

E. KraemerCSE 335: Software Design

Question

Assuming this interpretation of passive objects, how would we model the promotion of shared queue to a monitor?

E. KraemerCSE 335: Software Design

Question

Assuming this interpretation of passive objects, how would we model the promotion of shared queue to a monitor?

Answer: Two ways– Model the lock explicitly as another state machine– Use only a single state machine model for queue

rather than replicating per thread

E. KraemerCSE 335: Software Design

Model checking

Technique for exhaustively and automatically analyzing finite-state models to find “bad states”– Bad states are specified in a temporal logic or

some other declarative notationLots of tools that can be used for this purpose:

– FSP, SMV, Spin, etcIf you are designing concurrent software, want

to learn how to use these tools

E. KraemerCSE 335: Software Design

Wrap-up: Use of models

In this course, we have now used models for many purposes:– Documentation and demonstration of

characteristics of a complex design– Means for understanding the requirements of a

system to be built– Analysis for tricky concurrency properties

E. KraemerCSE 335: Software Design

Question

What does it mean to transition out of a concurrent composite state?

E. KraemerCSE 335: Software Design

Question

What does it mean to transition out of a concurrent composite state?

Two possible answers:– transition awaits completion of all concurrent

activities– transition acts immediately, terminating all

concurrent activities

E. KraemerCSE 335: Software Design

Example: Bridge game

E-W winsrubber

N-S winsrubberVulnerable

VulnerableNotVulnerable

NotVulnerable

ns-game ns-game

ew-game ew-game

PlayingRubber

Note: Transition out of PlayingRubber by one concurrent activity terminates the other

E. KraemerCSE 335: Software Design

Example: Cash dispenser

SetUp Completedo/ dispenseCash

do/ ejectCard

ready

Emitting

Note: Will not transition out of Emitting until after completion of all concurrent activities

E. KraemerCSE 335: Software Design

Recall: State explosion problem

Number of states in a system with multiple, orthogonal, behaviors grows exponentially (product of number of states of each feature)

Major impediment to understanding:– Impossible to visualize in any meaningful way– Requires the use of analysis tools to verify properties

Managing state explosion:– Concurrent state machines

• Each object in a system modeled as a state machine• Object state machine runs concurrently with those of other objects

– Concurrent composite states• Separates one machine can into orthogonal submachines

E. KraemerCSE 335: Software Design

Example: Concurrent composite state

TempOff

Automobile

Cooling

Heating

pushHeat pushAir

TempOn

pushHeat

pushAir

pushTCOff

Temperature control

Rear defroster

RDOff RDOnpushRD

pushRDRadOff RadOn

pushRad

pushRad

Radio control

Recommended