Sunteți pe pagina 1din 10

State

Machines for Event-Driven Systems | Miro Samek


State Machines for Event-Driven Systems


By Miro Samek


State machines are perhaps the most effective computation that may include manipulating the
method for developing robust event-driven hardware or generating "soft" events that
code for embedded systems. trigger other internal software components.
(That's why event-driven systems are
If you looked closely at just about any computer alternatively called reactive systems.) Once the
system around you, you'd probably find out event handling is complete, the software goes
that at any given time it is doing... nothing back to a dormant state (an idle loop or a
useful. That is, most of the time the CPU is power-saving mode) in anticipation of the next
either hibernating in one of its power-saving event.
modes or busily "twiddling its thumbs" by
executing an idle loop. (Modern PCs are Programmatically, this scheme implies that
particularly good at the latter form of doing upon arrival of an event the CPU executes only
nothing—they can "twiddle their thumbs" a a tiny fraction of the overall code. The main
billion times per second all while driving a challenge is to quickly pick and execute the
screen saver.) right code fragment. Indeed, you can trace the
whole progress in understanding reactive
This wasn't necessarily so throughout most of systems just by studying the methods used to
the history of computing. For decades, CPU pick the correct code to execute. The problem is
time was too expensive to be unused. not at all trivial and leads to control inversion
Consequently, the operating systems and compared to the traditional data-processing
applications were carefully designed to keep systems.
the CPU constantly busy with data-processing
tasks often organized into batch jobs. Only A conventional program (such as a compiler)
relatively recently, the nearly zero cost of starts off with some initial data (e.g., a source
processor time has radically changed the nature file), which it transforms by a series of
of computing. computations into the desired output data (an
object file), maintaining full control of the
These days, millions of PCs and billions of processing sequence from the beginning to the
embedded devices aren't processing batch jobs. end. In contrast, an event-driven program gains
Rather, almost all computers today are event- control only sporadically when handling events.
driven systems, which means that they The actions actually executed are determined
continuously wait for the occurrence of some by events, which arrive in largely unpredictable
external or internal event, such as a mouse order and timing, so the path through the code
click, a button press, a time tick, or an arrival of is likely to differ every time such software is
a data packet. After recognizing the event, they run. Moreover, a reactive system doesn't
react by performing the appropriate typically have a notion of progression from

www.barrgroup.com | Copyright Barr Group. All rights reserved. 1



State Machines for Event-Driven Systems | Miro Samek

beginning to end—the job of such a system is Oversimplification of the Event-Action


never done (unless explicitly terminated by an Paradigm
event). This paradigm still baffles many

programmers, who often find it strange,
All modern GUI development tools and
backwards, mind-boggling, or weird.
architectures seem to coalesce around the

event-action paradigm. The example published
Obviously, mastering the event-driven
in Constructing the User Interface with
computing model is particularly important for
Statecharts illustrates how this paradigm works
embedded developers, given that embedded
in practice.1 The author discusses a simple
systems are predominantly reactive by nature.
desktop calculator distributed as a sample
However, reactive systems are of fundamental
application with Microsoft Visual Basic, in which
importance across the whole software industry,
he found a number of serious problems. As
because reacting to events is what most
Horrocks notes, the point of this analysis is not
computers do most of the time. For example,
to criticize this particular application, but to
consider the ubiquitous GUI built into most PCs,
point out the shortcomings of the general
Macs, and Unix workstations.
principle used in its construction.


For the past two decades, the GUI has been the
focus of intense study both in the industry and
in academia with thousands of books and man-
years devoted to the problem. You might think,
therefore, that by now the event-driven
paradigm underlying all GUI architectures is
well understood and entirely under control.
Admittedly, GUI development made
tremendous progress from the arcane, black
magic approach (recall early-days Windows
programming), through application frameworks,
such as Microsoft's MFC, Borland's OWL, or Java Figure 1. (a) Visual Basic calculator GUI, and (b)
AWT, to RAD (rapid application development) the GUI after a crash with a run-time error.
tools, such as Microsoft Visual Basic or Boland
Delphi—especially the component-based For readers unfamiliar with Visual Basic, I will
approach originated by Visual Basic enabled GUI quickly summarize how the calculator
programming "for the masses." However, in application in Figure 1(a) is built. The basic steps
spite of all these powerful frameworks, tools, in creating a GUI application with any such tool
and components, astonishingly many GUIs are (not just with Visual Basic) are pretty much the
still lousy. I don't mean here just poorly same. First, you drag and drop various
designed human-machine interactions—I mean components from the tool palette to the screen
applications that crash, lock up, or mislead the designer window. In the case of the calculator,
user and are a nightmare for the maintainer you drag several buttons and a label for the
programmer. So, after all, perhaps display. After rearranging the components with
understanding of the event-driven paradigm the mouse, you set their properties, such as the
isn't that widespread among programmers. button captions, or the label color and font. At
this point—just after a few minutes—you have
a complete visual part of the interface. This is
fun! You can even launch the application and
play with it by pressing the buttons, moving it
around the screen, or minimizing the calculator

www.barrgroup.com | Copyright Barr Group. All rights reserved. 2



State Machines for Event-Driven Systems | Miro Samek

window. Of course, at this stage, the application when canceling an operand than canceling an
won't calculate anything. What's missing is the operator. As it turns out, the application
calculator-specific behavior. handles it the same way, regardless of the
context. At this point, you probably have
Adding the behavior requires some coding, but noticed an emerging pattern. The application is
also seems straightforward (initially, that is). especially vulnerable to events that require
Alongside properties, every component different handling depending on the context.
provides events, which are hooks for attaching
user code to be executed upon occurrence of Exercise: Ian Horrocks found 10 serious errors
the event. For example, the button component in this application just after an hour of testing.
provides the Click event, to which you can Try to find at least half of them.
attach a snippet of code that will be invoked
every time the user clicks the particular button. This is not to say that the calculator does not
In Visual Basic, you use the IDE to map the attempt to handle the context. To the contrary,
event to a Visual Basic procedure. In MFC, you if you look at the code, you'll notice that
use a message map macro to map an event to a managing the context is in fact the main
C++ class method. In Java 1.1, you register an concern of this application. The code is littered
event listener with the compatible event with a multitude of global variables and flags
source. Whichever way the mapping actually that serve only one purpose—handling the
occurs, all modern GUIs impose partitioning of context. For example, DecimalFlag indicates
the code by events to which the code responds. that a decimal point has been entered, OpFlag
represents a pending operation, LastInput
At first glance, this approach seems to work just indicates the type of the last button press
fine. Indeed, when you launch the calculator, event, NumOps denotes the number of
you will certainly find out that most of the time operands, and so on. With this representation,
it correctly adds, subtracts, multiplies, and the context of the computation is represented
divides. What's there not to like? However, play ambiguously, so it is difficult to tell precisely in
with the application for a while longer, and which mode the application is at any given time.
you'll discover many corner cases in which the
calculator provides misleading results, freezes, Actually, the application has no notion of any
or crashes altogether. single mode of operation, but rather tightly
coupled and overlapping conditions of
For example, the calculator often has problems operation determined by values of the global
with the "-" event—just try the following variables and flags. For example, the following
sequence of operations: 2, -, -, -, 2, =. The conditional logic attempts to determine
application crashes with a run-time error (see whether the "-" button-click event should be
Figure 1(b)). This is because the same button "-" treated as negation or subtraction:
is used to negate a number and to enter the
subtraction operator. The correct interpretation
of the "-" button-click event, therefore, Select Case NumOps
depends on the context, or mode, in which it Case 0
occurs. If Operator(Index).Caption = "-" And
LastInput <> "NEG" Then
Likewise, the CE (Cancel Entry) button ReadOut = "-" & ReadOut
occasionally works erroneously—try 2, x, CE, 2, LastInput = "NEG"
=, and observe that CE had no effect, even End If
though it appears to cancel the "2" entry from Case 1
the display. Again, CE should behave differently Op1 = ReadOut

www.barrgroup.com | Copyright Barr Group. All rights reserved. 3



State Machines for Event-Driven Systems | Miro Samek

If Operator(Index).Caption = "-" And neglects the latter dependency and leaves the
LastInput <> "NUMS" And handling of the context to largely ad-hoc
OpFlag <> "=" Then techniques. Sample applications such as the
ReadOut = "-" Visual Basic calculator have taught legions of
LastInput = "NEG" Visual Basic programmers to "handle" the
End If context with gazillions of variables and flags,
. . . with the obvious results. (For that matter, the
same can be said about MFC, Delphi, or
Exercise: Using the variables listed above, write Java/AWT/Swing programming.)
down the logical expression that would
determine whether the CE event should erase State Machines for Reactive Systems
the operand from the display.

For a better approach, let's turn back to the
Such an approach is fertile ground for bugs for
basics. The main challenge in programming
at least three reasons:
reactive systems is to identify the appropriate

actions to execute in reaction to a given event.
• It always leads to convoluted The actions are determined by two factors: by
conditional logic. the nature of the event and by the current
• Each branching point requires context (i.e., by the sequence of past events in
evaluation of a complex expression. which the system was involved). The traditional
• Switching between different modes techniques (such as the event-action paradigm)
requires modifying many variables, neglect the context and result in code riddled
which all can easily lead to with a disproportionate number of convoluted
inconsistencies. conditional logic (in C/C++, coded as deeply
nested if-else or switch-case statements). If you
Expressions like the one above, scattered could eliminate even a fraction of these
throughout the code, are unnecessarily complex conditional branches, the code would be much
and expensive to evaluate at run time. They are easier to understand, test, and maintain, and
also notoriously difficult to get right, even by the sheer number of convoluted execution
experienced programmers, as the bugs still paths through the code would drop radically,
lurking in the Visual Basic calculator attest. This perhaps by orders of magnitude. Techniques
approach is insidious because it appears to based on state machines are capable of
work fine initially, but doesn't scale up as the achieving exactly this—a dramatic reduction of
problem grows in complexity. Apparently, the the different paths through the code and
calculator application (overall only seven event simplification of the conditions tested at each
handlers and some 140 lines of Visual Basic branching point.
code, including comments) is just complex
enough to be difficult to get right with this A state machine makes the event handling
approach. explicitly dependent on both the nature of the
event and on the context (state) of the system.
The faults just outlined are rooted in the A state captures the relevant aspects of the
oversimplification of the event-action paradigm system's history very efficiently. For example,
used to construct this application. The when you strike a key on a keyboard, the
calculator example makes it clear, I hope, that character code generated will be either an
an event alone does not determine the actions uppercase or a lowercase character, depending
to be executed in response to that event. The on whether the Shift is active. Therefore, the
current context is at least equally important. keyboard is in the "shifted" state, or the
The prevalent event-action paradigm, however,

www.barrgroup.com | Copyright Barr Group. All rights reserved. 4



State Machines for Event-Driven Systems | Miro Samek

"default" state. The behavior of a keyboard through global variables). Obviously, this
depends only on certain aspects of its history, muddies the water and narrows the
namely whether Shift has been depressed, but applicability of the published state machine
not, for example, on how many and which code.
specific characters have been typed previously.
A state can abstract away all possible (but Nevertheless, I believe that the most popular
irrelevant) event sequences and capture only techniques can be distilled into the following
the relevant ones. three broad categories:

Standard Finite State Machine (FSM) • A nested switch statement with a scalar
"state variable" used as the
Implementations
discriminator in one level of the switch

and the event-type in the other. The
I suppose that most readers are familiar with technique is simple, but scales poorly
the classical FSMs (Finite State Machines) and because the entire state machine is
with their intuitive graphical representation, implemented as one monolithic switch
such as the UML state diagram of the Keyboard statement.
FSM shown in Figure 2.
• A state table containing an (typically

sparse) array of transitions for each
state. The table lists event types
(triggers) along one dimension and the
states along the other. Each cell in the
table contains a pointer to a function
(action to execute for the specific
event-state combination), as well as the
succeeding state. In effect, the table
approach converts the traditional
conditional code into a table lookup
Figure 2. UML state diagram representing the and allows changing the transition
keyboard state machine criteria by modifying data instead of
changing code.
However, when it comes to implementing state • Various object-oriented designs
machines (in C or C++, say), the literature on the representing a state machine as a
subject presents quite a cloudy picture. The dynamic tree-like structure of state and
main problem is that state machines cannot transition objects traversed at run time
operate in a vacuum and require, at a by a specialized "state machine
minimum, an execution context (thread) and an interpreter." To a large degree, this is a
event-dispatching mechanism. In any non-trivial generalized state table approach that
use, you also need to provide event-queuing attempts to represent a state machine
and timing services. All these elements strongly in a structure more memory-efficient
depend on the application domain and than an array (a network of objects in
operating system support (or lack thereof). this case).
Consequently, most writings present state
machines intimately intertwined with a specific All the popular state machine techniques are
concurrency model (e.g., polling loops or rather incompatible with the event-action
interrupt service routines) and geared toward a paradigm for at least two reasons. The event-
particular event dispatching policy (such as action paradigm already performs one level of
extracting events directly from hardware or event de-multiplexing based on the event type,

www.barrgroup.com | Copyright Barr Group. All rights reserved. 5



State Machines for Event-Driven Systems | Miro Samek

whereas the state machine techniques perform 20: #define FsmInit(me_, e_) (*(me_)-
de-multiplexing based on both the event type >state__)((me_), (e_))
and the current state. For example, the event- 21: #define FsmDispatch(me_, e_) (*(me_)-
action paradigm would slice a state table along >state__)((me_), (e_))
the state dimension, which would defuse the 22: #define FsmTran_(me_, targ_) ((me_)-
notion of state. >state__ = (State)(targ_))

State Machines in C and C++ Listing 1. The FSM header file

The other FSM elements in this implementation
Incidentally, the smallest, fastest, and arguably
include: the Event base class for derivation of
the most natural technique for implementing
events with parameters (Listing 1, lines 7-10)
state machines in C/C++ isn't widely publicized
and the Fsm base class for derivation of state
(although I suspect it's in every pro's bag of
machine objects (lines 13-22). (The sidebar
tricks). The technique hinges on pointers-to-
"Object-Oriented Programming (OOP) in C"
functions in C (and pointers-to-member-
explains techniques used to code classes and
functions in C++). Pointers-to-functions are
inheritance in C.)
obviously heavily used in other standard

techniques (e.g., state tables typically store
The Fsm class stores the current state in its
such pointers). However, the technique I
attribute state__ and provides four methods
mention here represents the very concept of
("inlined" by means of macros). The constructor
"state" directly as a pointer-to-function. Please
FsmCtor_ (Listing 1, line 19) initializes the
take note, the "state" isn't enumerated; it's not
current state, the method FsmInit() (line 20)
an instance of a State class—it is a pointer to a
triggers the initial transition, the method
state-handler function, as declared in line 4 of
FsmDispatch() (line 21) dispatches events to the
Listing 1.
state machine, and finally the method

FsmTran_() (line 22) takes a state transition.
1: typedef short Signal;

2: typedef struct Event Event;
1: #include "fsm.h"
3: typedef struct Fsm Fsm;
2:
4: typedef void (*State)(Fsm *, Event const *);
3: typedef struct Keyboard Keyboard;
5:
4: struct Keyboard
6: /* Event base class */
5: {
7: struct Event
6: Fsm super_; /* extend the Fsm class */
8: {
7: /* ... other attributes of Keyboard */
9: Signal sig;
8: };
10: };
9:
11:
10: void KeyboardCtor(Keyboard *me);
12: /* Finite State Machine base class */
11: void Keyboard_initial(Keyboard *me, Event
13: struct Fsm
const *e);
14: {
12: void Keyboard_default(Keyboard *me,
15: State state__; /* the current state */
Event const *e);
16: };
13: void Keyboard_shifted(Keyboard *me, Event
17:
const *e);
18: /* "inlined" methods of Fsm class */
14:
19: #define FsmCtor_(me_, init_) ((me_)-
15: typedef struct KeyboardEvt KeyboardEvt;
>state__ = (State)(init_))
16: struct KeyboardEvt
17: {

www.barrgroup.com | Copyright Barr Group. All rights reserved. 6



State Machines for Event-Driven Systems | Miro Samek

18: Event super_; /* extend the Event class */ 58: switch (e->sig)
19: char code; 59: {
20: }; 60: case SHIFT_RELEASED_SIG:
21: 61: printf("shifted::SHIFT_RELEASED");
22: /* signals used by the Keyboard FSM */ 62: FsmTran_((Fsm *)me,
23: enum &Keyboard_default);
24: { 63: break;
25: SHIFT_DEPRESSED_SIG, 64: case ANY_KEY_SIG:
26: SHIFT_RELEASED_SIG, 65: printf("key %c",
27: ANY_KEY_SIG, (char)toupper(((KeyboardEvt *)e)->code));
28: }; 66: break;
29: 67: }
30: void KeyboardCtor(Keyboard *me) 68: }
31: {
32: FsmCtor_(&me->super_, Listing 2. The Keyboard FSM implementation
&Keyboard_initial); (see state diagram from Figure 2)
33: }
34: Listing 2 shows an example of using the
35: void Keyboard_initial(Keyboard *me, Event technique to implement the Keyboard FSM
const *e) from Figure 2. Lines 3-13 declare the Keyboard
36: { FSM as a subclass of Fsm. (Please note the
37: /* ... initialization of Keyboard attributes member super_ in line 6.) Similarly, the
*/ keyboard-specific event KeyboardEvt is derived
38: printf("Keyboard initialized"); from Event in Listing 2, lines 16-20. The event
39: FsmTran_((Fsm *)me, types must be enumerated (lines 23-28), but
&Keyboard_default); the states aren't: they are referenced by the
40: } names of state-handler methods. The Keyboard
41: FSM has two such state-handlers
42: void Keyboard_default(Keyboard *me, (Keyboard_default() and Keyboard_shifted(),
Event const *e) declared in lines 12 and 13 of Listing 2,
43: { respectively). The Keyboard_initial() method
44: switch (e->sig) (declared in line 11 and defined in lines 35-40)
45: { implements the initial transition.
46: case SHIFT_DEPRESSED_SIG:
47: printf("default::SHIFT_DEPRESSED"); 1: int main()
48: FsmTran_((Fsm *)me, 2: {
&Keyboard_shifted); 3: Keyboard k;
49: break; 4: KeyboardCtor(&k);
50: case ANY_KEY_SIG: 5: FsmInit((Fsm *)&k, 0);
51: printf("key %c", 6: for (;;)
(char)tolower(((KeyboardEvt *)e)->code)); 7: {
52: break; 8: KeyboardEvt ke;
53: } 9: printf("\nSignal<-");
54: } 10: ke.code = getc(stdin);
55: 11: getc(stdin); /* discard '\n' */
56: void Keyboard_shifted(Keyboard *me, Event 12: switch (ke.code)
const *e) 13: {
57: {

www.barrgroup.com | Copyright Barr Group. All rights reserved. 7



State Machines for Event-Driven Systems | Miro Samek

14: case '^': ke.super_.sig = Exercise: Step through Listing 3 with a debugger
SHIFT_DEPRESSED_SIG; break; and look at the machine-language output
15: case '6': ke.super_.sig = generated by the FsmDispatch() method in line
SHIFT_RELEASED_SIG; break; 19. (It's typically only one instruction on a CISC
16: case '.': return 0; /* terminate the processor!) Compare it to code generated by a
test */ virtual method invocation in C++. Aren't they...
17: default: ke.super_.sig = ANY_KEY_SIG; identical?
break;
18: } Object-Oriented Programming (OOP) in
19: FsmDispatch((Fsm *)&k, (Event *)&ke);
C
/* dispatch */

20: }
Many programmers mistakenly think that
21: return 0;
Object-Oriented Programming (OOP) is possible
22: }
only with OO languages, such as C++ or Java.

However, OOP isn't the use of a particular
Listing 3. Test harness for the Keyboard FSM
language or a tool; it is a way of design that can

be implemented in almost any language, such
Listing 3 shows the test harness for the state
as C. Knowing how to code classes, inheritance,
machine implemented here as a console
and polymorphism in C can be very useful for
application driven from a keyboard with keys
embedded programmers, who often maintain C
"^" and "6" (which emulate pressing and
code or deal with embedded microprocessors
releasing Shift, respectively). Pressing "."
released to the field with nothing but a bare-
terminates the test. The essential elements
bones C compiler.
here are: instantiating the state machine object

(line 3), the explicit constructor call (hey, we are
As a C programmer, you already may have used
coding OOP in C), the state machine
ADTs (abstract data types). For example, in the
initialization in line 5, and dispatching events in
Standard C runtime library, the family of
line 19. Please note the necessity of explicit
functions that includes fopen(), fclose(), fread(),
casting (upcasting) to the Fsm superclass (in
and fwrite() operates on objects of type FILE.
lines 5 and 19), because the C compiler doesn't
"know" that Keyboard is related to (derived The FILE ADT is encapsulated so that the clients
have no need to access the internal attributes
from) Fsm.
of FILE. (When was the last time you looked up

what's inside the FILE structure?) You can think
Please note how the state machine approach
of the FILE structure and the associated
eliminates conditional statements from the
methods that operate on it as the FILE class.
code. Actually, in this particular technique even
The following bullet items summarize how the C
the explicit test of the current state variable
runtime library implements the FILE "class":
(the state__ member of the Fsm class)

disappears as a conditional statement and is
replaced with more efficient pointer-to-function • Attributes of the class are defined with
dereferencing (Listing 3, line 19). This coding a C struct (the FILE struct).
aspect is similar to the effect of polymorphism, • Methods of the class are defined as C
which eliminates many tests based on the type functions. Each function takes a pointer
of the object and replaces them with much to the attribute structure (FILE *) as an
more extensible (and efficient!) late binding. argument. Class methods typically
follow a common naming convention
(e.g., all FILE class methods start with f).

www.barrgroup.com | Copyright Barr Group. All rights reserved. 8



State Machines for Event-Driven Systems | Miro Samek

• Special methods initialize and clean up in C."7 Needless to say, Googling around for
the attribute structure (fopen() and "OOP in C" or "Inheritance in C" will reveal
fclose(), respectively). These methods countless other resources
play the roles of class constructor and [back]
destructor.

For example, Listing 2 declares class Keyboard.
Final Thoughts
Each method of the class takes the pointer to
the attribute stucture (Keyboard *) as the first See Introduction to Hierarchical State Machines
argument (the me pointer) and starts with the (HSMs) for a discussion of Hierarchical State
common class prefix (Keyboard). The me Machines.
pointer in C corresponds directly to the this
pointer in C++. (If you are unfamiliar with the In the context of the ubiquitous event-action
construct typedef struct Fsm Fsm, please refer paradigm, the State design pattern, as
to Dan Saks's Embedded Systems Programming described in Design Patterns by Erich Gamma
article "Tag vs. Type Names."2) and colleagues, 1995), takes on special
importance.8 This is the only state machine
A simple way of implementing single implementation to my knowledge that is
inheritance in C is by literally embedding the directly compatible with the event-action
superclass attribute structure as the first paradigm. I haven't listed this pattern among
member of the subclass structure. (Please the most popular techniques, because I don't
convince yourself that the resulting memory see it widely used (e.g., out of all Embedded
alignment lets you always treat any pointer to Systems Design state machine articles as of this
the subclass as a pointer to the superclass.) In writing, not a single one uses the State pattern).
particular, you can always pass this pointer to
any C function that expects a pointer to the Recently, a copy of Spencer Johnson's Who
superclass. (To be strictly correct in C, you Moved My Cheese? fell into my hands.9 The
should explicitly upcast this pointer.) Therefore, story takes place in a maze where four amusing
all methods designed for the superclass are characters look for "Cheese"—cheese being a
automatically available to subclasses; that is, metaphor for what we want in life. Obviously,
they are inherited. the maze is intended to be an allegory of life in
general, but it happens to describe
For example, Listing 2 shows how to derive class programmers' lives especially accurately. We
Keyboard from the base class Fsm (lines 4-8). programmers spend our working hours in the
The superclass instance super_ (Listing 2, line 6) most complicated maze of all (a.k.a. source
is embedded as the first attribute of the code) striving for our favorite kind of
subclass Keyboard. "Cheese"—robust, adaptable, and maintainable
software. We use different strategies to find our
For more information on implementing OOP in "Cheese": simple methods like trial-and-error,
C (including polymorphism, which I don't use in and sophisticated methods like object-oriented
the FSM example), see the first chapter of C+ programming, visual tools, and design patterns.
C++: Programming with Objects in C and C++ by Interestingly, techniques based on state
Allen Holub;3 Reusable Software Components, machines aren't among the popular,
Object-Oriented Embedded Systems mainstream programming strategies. Yet, state
Programming in C by Ted Van Sickle;4 C/C++ machines are perhaps the most effective
Users Journal articles from July 1990 and July method for developing robust event-driven
1993;5,6 or my Embedded Systems Programming code because they give us the map to the
article "Portable Inheritance and Polymorphism software maze.

www.barrgroup.com | Copyright Barr Group. All rights reserved. 9



State Machines for Event-Driven Systems | Miro Samek

Endnotes Related webinars and topics can be found at:


https://barrgroup.com/Embedded-
1. Horrocks, Ian. Constructing the User Interface Systems/How-To/Introduction-Hierarchical-
with Statecharts. Boston, MA: Addison-Wesley, State-Machines
1999. [back]
http://dl.acm.org/citation.cfm?id=520870
2. Saks, Dan. "Tag vs. Type Names." Embedded
Systems Programming, October, 2002. [back] http://dl.acm.org/citation.cfm?id=130373

3. Holub, Allen. C+ C++: Programming with http://dl.acm.org/citation.cfm?id=248984
Objects in C and C++. New York, NY: McGraw-
Hill, 1992. [back] http://dl.acm.org/citation.cfm?id=248984

4. Van Sickle, Ted. Reusable Software http://www.drdobbs.com/extending-c-for-
Components, Object-Oriented Embedded object-oriented-programm/184402731
Systems Programming in C. Prentice-Hall, 1997.
[back] https://books.google.com/books/about/Design
_patterns.html?id=6oHuKQe3TjQC&hl=en
5. Brumbaugh, David. "Object-Oriented
Programming in C." C/C++ Users Journal, July,
1990. [back]

6. Colvin, Gregory. "Extending C for Object-
Oriented Programming." C/C++ Users Journal,
July, 1993. [back]

7. Samek, Miro. "Portable Inheritance and
Polymorphism in C." Embedded Systems
Programming, December, 1997. [back]

8. Gamma, Erich; Helm, Richard; Johnson,
Ralph; Vlissides, John. Design Patterns. Addison-
Wesley, 1995. [back]

9. Johnson, Spencer. Who Moved My Cheese?.
G. P. Putnam's Sons, 1998. [back]










www.barrgroup.com | Copyright Barr Group. All rights reserved. 10

S-ar putea să vă placă și