First, the aggressivemarketing rhetoric of tool vendors has set unrealistically high expectations for purely visual programming andfully automatic code generation.. This also means thatt
Trang 1Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
Trang 2Table of Contents
Practical Statecharts in C/C++−Quantum Programming for Embedded Systems 1
Preface 3
Mission 3
Why Quantum Programming? 4
QP versus XP and Other Agile Methodologies 5
Audience 6
Guide to Readers 7
Acknowledgments 8
Part I: Statecharts 10
Chapter List 10
Chapter 1: Whirlwind Tour of Quantum Programming 11
Overview 11
1.1 The Ultimate Hook — Anatomy of a GUI Application 11
1.2 A Better Way of Programming — A Calculator That Works 13
1.2.1 Shortcomings of the Traditional Event–Action Paradigm 13
1.2.2 Calculator Statechart 14
1.2.3 Integration with Windows 17
1.2.4 State Handler Methods 18
1.3 Object−Oriented Analogy 20
1.3.1 State Hierarchy and Class Taxonomy 20
1.3.2 Entering/Exiting States and Instantiating/Finalizing Classes 21
1.3.3 Programming−by−Difference 21
1.3.4 Behavioral Inheritance as a Fundamental Meta−Pattern 21
1.3.5 State Patterns 21
1.3.6 Refactoring State Models 22
1.3.7 Beyond Object−Oriented Programming 22
1.4 Quantum Analogy 23
1.5 Summary 23
Chapter 2: A Crash Course in Statecharts 25
Overview 25
2.1 The Essence of Finite State Machines 25
2.1.1 States 26
2.1.2 Extended States 26
2.1.3 Guards 27
2.1.4 Events 27
2.1.5 Actions and Transitions 28
2.1.6 Mealy and Moore Automata 28
2.1.7 Execution Model — Run−to−Completion Step 28
2.1.8 State Transition Diagrams 29
2.2 The Essence of UML Statecharts 30
2.2.1 Hierarchical States 30
2.2.2 Behavioral Inheritance 31
2.2.3 Orthogonal Regions 33
2.2.4 Entry and Exit Actions 34 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
i
Trang 3Table of Contents
Chapter 2: A Crash Course in Statecharts
2.2.5 Transition Execution Sequence 35
2.2.6 Internal Transitions 36
2.2.7 Pseudostates 36
2.2.8 Refined Event Handling 37
2.2.9 Semantics versus Notation 37
2.2.10 Statecharts versus Flowcharts 38
2.2.11 Statecharts and Automatic Code Synthesis 38
2.3 Examples of State Models 39
2.3.1 Quantum Calculator 40
2.3.2 Hydrogen Atom 42
2.4 Summary 45
Chapter 3: Standard State Machine Implementations 47
Overview 47
3.1 State Machine Interface 47
3.2 Nested switch Statement 48
3.3 State Table 51
3.4 State Design Pattern 54
3.5 Optimal FSM Implementation 57
3.6 State Machines and C++ Exception Handling 60
3.7 Role of Pointer−to−Member Functions 60
3.8 Implementing Guards, Junctions, and Choice Points 62
3.9 Implementing Entry and Exit Actions 63
3.10 Dealing with State Hierarchy 63
3.11 Summary 64
Chapter 4: Implementing Behavioral Inheritance 66
Overview 66
4.1 Structure 67
4.1.1 Events 69
4.1.2 States 71
4.1.3 Entry/Exit Actions and Initial Transitions 72
4.1.4 State Transitions 73
4.1.5 The top State and the initial Pseudostate 74
4.2 An Annotated Example 75
4.2.1 Enumerating Signals and Subclassing QHsm 76
4.2.2 Defining State Handler Methods 77
4.2.3 Initialization and Dispatching Events 79
4.2.4 Test Run 80
4.3 Heuristics and Idioms 81
4.3.1 Structuring State Machine Code 81
4.3.2 Choosing the Right Signal Granularity 83
4.3.3 UML−Compliant HSMs 83
4.4 The Event Processor 85
4.4.1 Initializing the State Machine: The init() Method 85
4.4.2 Dispatching Events: The dispatch() Method 86
4.4.3 Static and Dynamic State Transitions: Macros Q_TRAN() and Q_TRAN_DYN() 87 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
ii
Trang 4Table of Contents
Chapter 4: Implementing Behavioral Inheritance
4.4.4 Dynamic State Transition: The tran() Method 88
4.4.5 Static State Transition: The tranStat() Method and the Tran Class 92
4.4.6 Initializing the QTran Object: The tranSetup() Method 93
4.5 C Implementation 95
4.5.1 QHsm Class in "C+" 96
4.5.2 QHsm Constructor and Destructor 96
4.5.3 State Handler Methods and Pointer−to−Member Functions 97
4.5.4 QHsm Methods 97
4.5.5 Statechart Example in C 98
4.6 Caveats 99
Chapter 5: State Patterns 102
Overview 102
5.1 Ultimate Hook 103
5.1.1 Intent 103
5.1.2 Problem 103
5.1.3 Solution 103
5.1.4 Sample Code 104
5.1.5 Consequences 106
5.2 Reminder 106
5.2.1 Intent 106
5.2.2 Problem 107
5.2.3 Solution 107
5.2.4 Sample Code 107
5.2.5 Consequences 110
5.3 Deferred Event 111
5.3.1 Intent 111
5.3.2 Problem 111
5.3.3 Solution 111
5.3.4 Sample Code 112
5.3.5 Consequences 114
5.4 Orthogonal Component 115
5.4.1 Intent 115
5.4.2 Problem 115
5.4.3 Solution 115
5.4.4 Sample Code 117
5.4.5 Consequences 121
5.5 Transition to History 122
5.5.1 Intent 122
5.5.2 Problem 123
5.5.3 Solution 123
5.5.4 Sample Code 123
5.5.5 Consequences 125
5.6 Summary 126 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
iii
Trang 5Table of Contents
Chapter 6: Inheriting State Models 127
Overview 127
6.1 Statechart Refinement Example in C++ 128
6.1.1 How Does It Work? 131
6.2 Statechart Refinement Example in C 134
6.2.1 Preparing a "C+" State Machine for Polymorphism 134
6.2.2 Inheriting and Refining the "C+" State Machine 135
6.3 Caveats 137
6.3.1 Static versus Dynamic State Transitions 137
6.3.2 Multiple Inheritance 137
6.3.3 Heuristics for Inheriting and Refining Statecharts 138
6.4 Summary 140
Part II: Quantum Framework 142
Chapter List 142
Chapter 7: Introducing the Quantum Framework 143
Overview 143
7.1 Conventional Approach to Multithreading 144
7.1.1 Dining Philosophers − Conventional Approach 144
7.1.2 Therac−25 Story 147
7.2 Computing Model of the QF 148
7.2.1 Active Object−Based Multithreading 149
7.2.2 Quantum Analogy 150
7.2.3 Publish−Subscribe Event Delivery 151
7.2.4 General Structure 152
7.2.5 Dining Philosophers Revisited 152
7.3 Roles of the QF 154
7.3.1 Source of Conceptual Integrity 155
7.3.2 RTOS Abstraction Layer 155
7.3.3 Software Bus 156
7.3.4 Platform for Highly Parallel Computing 157
7.3.5 Basis for Automatic Code Generation 158
7.4 Summary 159
Chapter 8: Design of the Quantum Framework 161
Overview 161
8.1 Embedded Real−Time Systems 161
8.2 Handling Errors and Exceptional Conditions 163
8.2.1 Design by Contract 164
8.2.2 State−Based Handling of Exceptional Conditions 166
8.3 Memory Management 168
8.3.1 A Heap of Problems 168
8.3.2 Memory Management in the QF 170
8.4 Mutual Exclusion and Blocking 171
8.4.1 Perils of Mutual Exclusion 172
8.4.2 Blocking in Active Object−Based Systems 174
8.5 Passing Events 175 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
iv
Trang 6Table of Contents
Chapter 8: Design of the Quantum Framework
8.5.1 Dynamic Event Allocation 176
8.5.2 Publish−Subscribe Model 178
8.5.3 Multicasting Events 182
8.5.4 Automatic Event Recycling 183
8.6 Active Objects 184
8.6.1 Internal State Machine 185
8.6.2 Event Queue 185
8.6.3 Thread of Execution 186
8.7 Initialization and Cleanup 188
8.7.1 Initializing the Framework 188
8.7.2 Starting the QF Application 189
8.7.3 Gracefully Terminating the QF Application 189
8.8 Time Management 190
8.8.1 QTimer Class 190
8.8.2 Clock Tick, QF::tick() Method 191
8.9 QF API Quick Reference 192
8.9.1 QF Interface 192
8.9.2 QActive Interface 193
8.9.3 QTimer Interface 194
8.10 Summary 195
Chapter 9: Implementations of the Quantum Framework 197
Overview 197
9.1 The QF as a Parnas Family 197
9.2 Code Organization 198
9.2.1 Directory Structure 199
9.2.2 Public Scope Header File 200
9.2.3 Package Scope Header File 201
9.3 Common Elements 202
9.3.1 Critical Section 202
9.3.2 Event Pool 203
9.3.3 Event Queue 205
9.4 DOS: The QF without a Multitasking Kernel 210
9.4.1 Foreground/Background Processing 210
9.4.2 Foreground/Background with the QF 211
9.4.3 DOS−Specific Code 214
9.4.4 Benefits of the QF in a Foreground/Background System 215
9.5 Win32: The QF on the Desktop 216
9.5.1 Critical Section, Event Queue, and Execution Thread 216
9.5.2 Clock Tick 218
9.6 RTKernel−32: The QF with a Preemptive Priority−Based Kernel 219
9.6.1 Critical Section and Event Pool 220
9.6.2 Event Queue and Execution Thread 221
9.6.3 RTKernel−32 Initialization and Clock Tick 223
9.6.4 Cross−Development with RTKernel−32 224
9.7 Summary 225 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
v
Trang 7Table of Contents
Chapter 10: Sample Quantum Framework Application 226
Overview 226
10.1 Generating a QF Application 226
10.1.1 Signals and Events 227
10.1.2 Table Active Object 228
10.1.3 Philosopher Active Object 230
10.1.4 Deploying the DPP 232
10.1.5 Notes 232
10.2 Rules for Developing QF Applications 234
10.3 Heuristics for Developing QF Applications 235
10.4 Sizing Event Queues and Event Pools 236
10.4.1 Event Queues 236
10.4.2 Event Pools 238
10.5 System Integration 239
10.6 Summary 239
Chapter 11: Conclusion 241
Overview 241
11.1 Key Elements of QP 241
11.1.1 A Type of Design, Not a Tool 242
11.1.2 A Modeling Aid 242
11.1.3 A Learning Aid 243
11.1.4 A Useful Metaphor 243
11.2 Propositions of QP 244
11.2.1 Quantum Programming Language 245
11.2.2 RTOS of the Future 245
11.2.3 Hardware/Software Codesign 246
11.3 An Invitation 246
Appendix A: "C+" − Object−Oriented Programming in C 248
Overview 248
A.1 Abstraction 249
A.2 Inheritance 251
A.3 Polymorphism 253
A.4 Costs and Overheads 258
A.5 Summary 259
Appendix B: Guide to Notation 261
Overview 261
B.1 Class Diagrams 261
B.2 Statechart Diagrams 262
B.3 Sequence Diagrams 263
B.4 Timing Diagrams 264
Appendix C: CD−ROM 265
Overview 265
C.1 Source Code Structure 266
C.2 Installation 266 Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
vi
Trang 8Table of Contents
Appendix C: CD−ROM
C.2.1 Source Code 266
C.2.2 On Time RTOS−32 Evaluation Kit 266
C.2.3 Adobe Acrobat Reader 266
C.3 Answers to the Exercises 267
C.4 Resources 267
Bibliography 268
Practical Statecharts in C/C++: Quantum Programming for Embedded Systems
vii
Trang 9Practical Statecharts in C/C++−Quantum
Programming for Embedded Systems
appropriate companies for more complete information on trademarks and trademark registrations All
trademarks and registered trademarks in this book are the property of their respective holders
Copyright © 2002 CMP Books
except where noted otherwise Published by CMP Books, CMP Media LLC All rights reserved No part ofthis publication may be reproduced or distributed in any form or by any means, or stored in a database orretrieval system, without the prior written permission of the publisher
The programs in this book are presented for instructional value The programs have been carefully tested, butare not guaranteed for any particular purpose The publisher does not offer any warranties and does notguarantee the accuracy, adequacy, or completeness of any information herein and is not responsible for anyerrors or omissions The publisher assumes no liability for damages resulting from the use of the information
in this book or for any infringement of the intellectual property rights of third parties that would result fromthe use of this information
Acquisitions Editor: Robert Ward
Technical Editor: Jeff Claar
Editors: Catherine Janzen, Julie McNamee, and Rita Sooby
Layout design & production: Justin Fulmer
Managing Editor: Michelle O'Neal
Cover art design: Rupert Adley and Damien Castaneda
Distributed in the U.S by:
Publishers Group West
1700 Fourth Street
Berkeley, California 94710
1−800−788−3123
http://www.pgw.com
Distributed in Canada by:
Jaguar Book Group
100 Armstrong Avenue
Georgetown, Ontario M6K 3E7 Canada
Practical Statecharts in C/C++−Quantum Programming for Embedded Systems 1
Trang 11This heavy reliance on tools has affected the software community in three ways First, the aggressive
marketing rhetoric of tool vendors has set unrealistically high expectations for purely visual programming andfully automatic code generation Second, the rhetoric of the argument for automatic code synthesis
depreciated the role of manual coding Finally, the accidental association between statecharts and CASE(computer−aided software engineering) tools gave rise to a misconception that the more advanced UMLconcepts, such as statecharts, are only viable in conjunction with sophisticated code−synthesizing tools
The reality is that CASE tools haven't made manual coding go away Even the best−in−class
code−synthesizing tools can generate only a fraction of the software (the so−called housekeeping code
[Douglass 99]) The difficult, application−specific code still must be written explicitly (although it is typicallyentered through the dialog boxes of a tool rather than typed into a programming editor) This also means thatthe models are not purely visual, but a mixture of diagrams and textual information (mostly snippets of code
in a concrete programming language)
Moreover, for many projects, a design automation tool is not the best solution The fundamental problem, asalways, is the cost versus the return Even if you ignore the dollar cost of the tool, you must ask whether the
benefits outweigh the compounded complexity of the problem and the tool The complete cost function must
also include training and adaptation of the existing infrastructure to the tool (e.g., the
compiler/linker/debugger tool chain, the host and target operating systems, the directory structure and filenames, version control, and the software build process) After weighing all the pros and cons and strugglingwith a tool for a while, many teams notice that they spend more time fighting the tool than solving problems.For many developers, the tool simply can't pull its own weight and ends up as shelfware or a not−so−simpledrawing tool
Mission
My primary mission in this book is to offer a simple, lightweight alternative to a design automation tool byproviding concrete, efficient, and proven implementations of statecharts that every practitioner reasonablyproficient in C or C++ can start using within days
To achieve these goals, I describe the major components of every typical code−synthesizing tool
The techniques needed to implement and use UML statecharts — the main constructive element in the
UML specification (presented in Part I)
•
A real−time application framework — a complete software infrastructure for executing statecharts,tailored to embedded real−time systems and based on active objects and asynchronous event passing(presented in Part II)
•
Trang 12At first glance, the approach can be classified as a set of common elaborative techniques for implementingUML models Even as such, it spares many practitioners from reinventing the wheel In this book, I presentreadyưtoưuse, generic, and efficient elements that you can use to implement and execute hierarchical statemachines; generate, queue, and dispatch events; integrate state machines with realưtime operating systems(RTOSs); and much more These software elements vary little from system to system but are hard to find inthe literature It's even harder to make them work well together The value of this book is similar to that of amultivitamin pill: in one fell swoop (or a few chapters in this case), you get all the necessary ingredients, wellbalanced and complementing each other If you use this book only in this manner, my most important goal isalready accomplished.
Why Quantum Programming?
By providing concrete implementations of such fundamental concepts as statecharts and statechartưbasedcomputing models, the book lays the groundwork for a new programming paradigm, which I propose to callQuantum Programming (QP) I chose this name to emphasize the striking and fundamental analogy betweenreactive software systems and microscopic objects As the laws of quantum mechanics describe, at the
fundamental level, most microscopic objects (such as elementary particles, nuclei, atoms, and molecules)exhibit state behavior Quantum objects are, in fact, little state machines, which spend their lives in strictlydefined, discrete quantum states and can change state only in certain ways via uninterruptible transitionsknown as quantum leaps Correspondingly, QP models state transitions with runưtoưcompletion (RTC) steps.The only way quantum systems interact with one another is through an exchange of field quanta (intermediatevector bosons), which are mediators of fundamental forces.[1] Similarly, QP requires reactive systems tointeract only by exchanging event instances I explain more about this quantum analogy in Chapters 1, 2, and7
As a programming paradigm, QP has much more to offer than merely the snippets of code published in thisbook I see and use QP as a set of techniques that increases the level of abstraction of a conventional
programming language (such C or C++) The additional abstractions in QP allow me to efficiently modelreactive systems directly in C++ or C The role of QP can be compared to that of an objectưoriented (OO)programming language Just as Smalltalk, C++, or Java enable objectưoriented programming (OOP) throughdirect support for the three fundamental OO design metaưpatterns — abstraction, inheritance, and
polymorphism — QP enables statechart modeling directly in C or C++ through another fundamental
metaưpattern: the hierarchical state machine (HSM) Currently, the fundamental HSM pattern is an externaladdưon to C++ or C, but there is no reason it couldn't be natively supported by a quantum programminglanguage in the same way that abstraction, inheritance, and polymorphism are natively supported by OOprogramming languages (Indeed, in Appendix A, you see that OOP can be supported as an "add–on" inprocedural languages such as C by explicitly applying the three fundamental OO patterns I subsequently usethis augmented C, which I call "C+", to develop the C implementation of the HSM pattern.)
The relationship between QP and OOP is interesting On one hand, the most important aspects of QP, such asthe HSM design pattern and the asynchronous communication paradigm, are orthogonal to OOP, which is anindication that these aspects of QP might be fundamental On the other hand, however, these concepts workbest when applied with OOP In fact, a deep analogy exists between OOP and QP, which I discuss in Chapter
1 In this sense, QP builds on top of OOP, complements it, and extends it into the domain of reactive systems.Most of the concepts that form QP are not new, but, rather, draw on a broad range of longưknown techniquesand methodologies from programming and other disciplines such as quantum field theory Most inspiring to
me was the realưtime objectưoriented modeling (ROOM) method described by Bran Selic and colleagues[Selic+ 94] Specifically, the realưtime framework, or Quantum Framework, first began as a radically
simplified ROOM virtual machine Other influences were the classical Gang of Four design patterns
[Gamma+ 95], the UML specification [OMG 01] (especially the state machine package), the original works of
Trang 13Harel [Harel 87, Harel+ 98], and books by Bruce Douglass [Douglas 99, Douglas 99a] The Douglass writings
in many ways are on the opposite end of the spectrum from QP, because QP offers mostly alternative viewsand complementary techniques to those he describes For example, the state patterns he pioneered rely heavily
on orthogonal regions, whereas QP shows how to implement some of these more elegantly using state
Nonetheless, even with QP (or any CASE tool, for that matter), programming reactive systems remainsdifficult because it is by nature difficult As Frederick Brooks [Brooks 87] notes in his classic essay "NoSilver Bullet", you can only attack the accidental difficulties and can't do much about the essential ones, atleast not in software alone In this context, QP exactly follows Brooks' advice — to attack and remove theaccidental difficulties associated with developing event−driven software
[1]
For example, photons mediate the electromagnetic force, gluons the strong force, and bosons W± and Zo theweak interactions
QP versus XP and Other Agile Methodologies
QP is not a programming methodology; it is a set of concrete techniques for modeling and implementingreactive systems Nevertheless, the QP approach is an expression of a basic programming philosophy, which
is closely aligned with the recent trends in software development known collectively as light or agile
methodologies Some of these technologies include eXtreme Programming (XP), Crystal methodologies,SCRUM, Adaptive Software Development, Feature−Driven Development, and Agile Modeling The basicphilosophy behind the new approaches is best summarized in the "Agile Manifesto" [Fowler 01], in which the
"seventeen anarchists" agree to value (1) individuals and interactions over processes and tools and (2)
working software over comprehensive documentation
In the context of QP, valuing individuals and interactions over processes and tools means putting emphasis onunderstanding the underlying implementations and mechanisms rather than on hiding the complexity behind a
tool (the practice that Anders Hejlsberg [Hejlsberg 01] denounced as "simplexity–complexity wrapped in something simple") Real−life experience has shown repeatedly that if an individual understands the
underlying implementation model, then he or she can code more efficiently and work with greater confidence.For example, determining which actions fire in which sequence in a nontrivial state transition is not somethingyou should guess at or discover by running a tool−supported animation of your statechart The answer shouldcome from your understanding of the underlying implementation (discussed in Chapters 3 and 4) Even if youdecide to use a design automation tool and even if your particular tool uses slightly different statechart
implementation techniques than those I discuss in this book, you will still be a better, more productive, andconfident user of the tool because of your understanding of the fundamental mechanisms
In addition to putting value on individuals and interactions by explaining low−level fundamental softwarepatterns, QP also offers powerful high−level metaphors, such as the quantum−mechanical and object−orientedanalogies A metaphor is valuable because it promotes the conceptual integrity of a software product andprovides a common vocabulary, which dramatically improves communication among all of the stakeholders.Agile methodologies recognize the importance of such metaphors (e.g., XP proposes the development of a
Trang 14metaphor as a key practice).
As an elaborative approach, QP values working software over comprehensive documentation In fact, QPoffers nothing but the working code I have made every attempt to provide only executable code, so that youcan try out virtually every listing and code snippet you find in this book, as well as the code available only onthe accompanying CDưROM Because only executable code is testable, this aspect of QP goes handưinưhandwith the requirement for continuous testing, which is inherent to all agile methodologies
In addition to offering techniques for creating executable code, QP also offers highly readable,
selfưdocumenting code For example in Chapter 4, I give directions on how to make the structure of a
statechart clearly apparent from the code and almost equivalent to a UML state diagram This is not to say that
QP abandons UML diagrams or makes them obsolete To the contrary, in this book, you will see quite a fewdiagrams that follow UML notation strictly (although because I used a simple drawing tool, they cannot becalled UMLưcompliant) When it comes to diagrams and other visual models, QP shares the commonsenseview of Agile Modeling [Ambler 01] The most important role of visual models is to help you think throughthe designs and communicate them to programmers, customers, or management For that purpose, simpletools like paper and pencil, whiteboard, or sticky notes are usually sufficient It is also OK to discard thevisual models after they have fulfilled their purpose The specific value of visual modeling lies in tapping thepotential of high bandwidth spatial intelligence, as opposed to lexical intelligence used with textual
information
Incomplete, disposable visual models, however, can't be used for code synthesis In this respect, the agileapproach fails to take advantage of the constructive aspect of some visual representations, such as UMLstatecharts QP complements agile methodologies by enabling highưlevel modeling directly at the code level.With the concrete, readyưtoưuse building blocks provided by QP, you can construct, compile, and executeconcurrent state models rapidly, even if they are nothing more than vastly incomplete skeletons As you willsee in Chapter 4, you can change the state machine topology (e.g., add, remove, or rearrange states andtransitions) at any stage, even late in the process, by changing a few lines of code and recompiling Then youcan test your executable model on the host or target environments Plenty of such executable models areincluded throughout this book In that way, you can quickly try out many alternatives before committing toany one of them This process is rightly called modeling, rather than coding, because your goal isn't thegeneration of a final product or even a prototype, but rather the fast exploration of your design space
Admittedly with such lightweight modeling, you lose the benefits of spatial intelligence As mentioned earlier,modeling at the code level does not preclude using UML diagrams or lowưfidelity sticky notes as models ofuser interfaces Indeed, spatial intelligence is best at grasping highưlevel structures and patterns when themodels are relatively high level and uncluttered As the models become more detailed, lexical intelligence
usually takes over anyway because, in the end, "programming is all about text" [Hejlsberg 01].
•
Users of design automation tools will better understand the inner workings of their tools, helping them
to use the tools more efficiently and confidently
•