10. Comparison to the Traditional Approach

This QP/C++ Tutorial is adapted from Chapter 1 of Practical UML Statecharts in C/C++, Second Edition
by Miro Samek, the founder and president of Quantum Leaps, LLC.

qp_tutorial.jpg

Prev: 9. Using Software Tracing for Testing and Debugging
Next: 11. Summary

The "Fly 'n' Shoot" game behaves intentionally almost identically to the "Quickstart" application provided in source code with the Luminary Micro ARM Cortex-M3 LM3S811 evaluation kit (http://www.luminarymicro.com). In this section I'd like to compare the traditional approach represented by the "Quickstart" application with the state machine-based solution exemplified in the "Fly 'n' Shoot" game.

Figure 10-1(a) shows schematically the flowchart of the "Quickstart" application, while Figure 10-1(b) shows the flowchart of the "Fly 'n' Shoot" game running on top of the cooperative "vanilla" kernel. At the highest level, the flowcharts are similar in that they both consist of an endless loop surrounding the entire processing. But the internal structure of the main loop is very different in the two cases. As indicated by the heavy lines in the flowcharts, the "Quickstart" application spends most of its time in the tight "event loops" designed to busy-wait for certain events, such as the screen update event. In contrast, the "Fly 'n' Shoot" application spends most of its time right in the main loop. The QP framework dispatches any available event to the appropriate state machine that handles the event and returns quickly to the main loop without ever waiting for events internally.

Fig1.11.jpg

Figure 10-1 The control flow in the

Quickstart" application (a), and the Fly 'n' Shoot example (b). The heavy lines represent the most frequently exercised paths through the code."

The "Quickstart" application has much more convoluted flow of control than the "Fly 'n' Shoot" example, because the traditional solution is very specific to the problem at hand while the state-machine approach is generic. The "Quickstart" application is structured very much like a traditional sequential program that tries to stay in control from the beginning to the end. From time to time, the application pauses to busy-wait for a certain event, whereas the code is generally not ready to handle any other events than the one it chooses to wait for. All this contributes to the inflexibility of the design. Adding new events is hard because the whole structure of the intervening code is designed to accept only very specific events and would need to change dramatically to accommodate new events. Also, while busy-waiting for the screen update event (equivalent to the TIME_TICK event in "Fly 'n' Shoot" example) the application is really not responsive to any other events. The task-level response is hard to characterize and generally depends on the event type. The timing established by the hard-coded waiting for the existing events might not work well for new events.

In contrast, the "Fly 'n' Shoot" application has a much simpler control flow that is purely event-driven and completely generic (see Figure 10-1(b)). The context of each active object component is represented as the current state of a state machine, rather than as a certain place in the code. That way, hanging in tight "event loops" around certain locations in the code corresponding to the current context is unnecessary. Instead, a state machine remembers the context very efficiently as a small data item (the state-variable, see Chapter 3 of Practical UML Statecharts in C/C++, Second Edition). After processing of each event the state machine can return to the common event loop that is designed generically to handle all kinds of events. For every event, the state machine naturally picks up where it left off and moves on to the next state, if necessary. Adding new events is easy in this design, because a state machine is responsive to any event at any time. An event-driven, state-machine-based application is incomparably more flexible and resilient to change than the traditional one.

Note:
The generic event loop can also very easily detect the situation when no events are available, in which case the QP framework calls the QF::onIdle() function (see Figure 10-1(b)). This callback function is designed to be customized by the application and is the ideal place to put the CPU in a low-power sleep mode to conserve the power. In contrast, the traditional approach does not offer any single place to transition to the low-power sleep mode, and consequently is much less friendly for implementing truly low-power designs.

Prev: 9. Using Software Tracing for Testing and Debugging
Next: 11. Summary

logo_ql_TM.jpg

Copyright © 2002-2010 Quantum Leaps, LLC. All Rights Reserved.
http://www.state-machine.com

Generated on Tue Mar 16 19:39:10 2010 for QP/C++ by  doxygen 1.6.3