![]() |
![]() |
![]() |
![]() |
![]() |
Example Section
In this section a complete example of an application is presented. The application is simple but it still contains most of the problems that arise when the Cadvanced SDL to C Compiler is used to generate applications. All source code for this example, together with the running application are delivered with the runtime libraries for application generation. Note that the example is developed for SunOS 5. The example is not updated to use encoding and decoding support.
The Example
We want to develop an application that consists of several communicating UNIX processes. Each UNIX process should also be connected to the keyboard and the screen. When a complete line is typed on the keyboard (when <Return> is pressed) in one of the UNIX processes, that line should be sent to and printed by all the UNIX processes, including the one where the line was entered. If a line starting with the character "." is entered in any UNIX process then all the UNIX processes should terminate immediately.
There are some observations we can make from this short description.
- Firstly, all the UNIX processes should behave exactly the same, which means that the behavior can be described in one SDL system and one application can be generated. This application should be able to communicate with other instances of itself and should simultaneously be started in as many instances as we want communicating UNIX processes.
- Secondly, each UNIX process needs access to the terminal. To simplify the connection between a UNIX process and the terminal, we assume that each instance of the application is started from its own window (its own shell tool). In this way the underlying window manager will solve the problem of directing input typed on the keyboard to the correct application, as well as making it possible for you to distinguish between output from different applications.
- Thirdly, the UNIX processes have to be connected so they can communicate with each other. We have decided to use sockets as communication media, and to let the UNIX processes form a ring. This means that when a UNIX process receives a message containing a line, it should print the line and send the message on to the next UNIX process in the ring, if it did not itself originally send the line message.
The SDL System
The SDL system with a behavior as outlined above is very simple. It contains, for example, only one process. The system can receive three types of signals, TermInput from the terminal, and Message and Terminate from the SDL system that is the previous node in the ring. The system will respond by sending Display to the terminal and Message and Terminate to the SDL system next in the ring. The signals TermInput and Display take a line (which is read from the terminal or should be printed on the terminal) as parameter. The signal Message takes a line and a PId value (the original sender in the ring) as parameter, while the signal Terminate takes a PId value (the original sender in the ring) as parameter.
The diagrams for the SDL system may be found in Appendix C: The SDL System. In the section Where to Find the Example, references to where to find the source code for this example are given.
Simulating the Behavior
At this stage of the development of the application, when the SDL system is completed but the environment functions are not implemented, it is time to simulate the SDL system to debug it at the SDL level. The runtime library Simulation is appropriate in this case for simulation.
There are six cases that should be tested:
- If TermInput (with a line not starting with a period) is sent to the system, it should respond by sending a Message signal to the environment. The first parameter in this signal should be equal to the parameter in the received TermInput signal. The second parameter should be the PId value of the sending process.
- If TermInput (with a line starting with a period) is sent to the system, it should respond by sending a Terminate signal to the environment. The parameter should be the PId value of the sending process.
- If Message (with a PId parameter not equal to the receiving process) is sent to the system, it should respond by sending a copy of the Message signal to the environment. It should also send Display to the environment with the received line as parameter.
- If Message (with a PId parameter equal to the receiving process) is sent to the system, it should respond by just sending a Display signal to the environment with the received line as parameter.
- If Terminate (with a PId parameter not equal to the receiving process) is sent to the system, it should respond by sending a copy of the Terminate signal to the environment. The execution of the program should then terminate.
- If Terminate (with a PId parameter equal to the receiving process) is sent to the system, the program should just stop executing.
Let us now verify that the SDL system behaves according to this. In the two executions of the simulation shown below, the cases described above are tested in the same order as they are listed.
Example 444 : Execution Trace of Generated Application
Command : set-trace 6Default trace set to 6Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : start state* Now : 0.0000*** NEXTSTATE idleCommand : output-viaSignal name : TermInputParameter 1 (charstring) : `hello'Channel name :Signal TermInput was sent to PhonePr:1 from env:1Process scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : TermInput* Sender : env:1* Now : 0.0000* Parameter(s) : `hello'* DECISION Value: true* DECISION Value: false* OUTPUT of Message to env:1* Parameter(s) : `hello', PhonePr:1*** NEXTSTATE idleCommand : output-via TermInput `.' -Signal TermInput was sent to PhonePr:1 from env:1Process Scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : TermInput* Sender : env:1* Now : 0.0000* Parameter(s) : `.'* DECISION Value: true* DECISION Value: true* OUTPUT of Terminate to env:1* Parameter(s) : PhonePr:1*** NEXTSTATE idleCommand : output-via MessageParameter 1 (charstring) : `hello'Parameter 2 (pid) : envChannel name :Signal Message was sent to PhonePr:1 from env:1Process scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : Message* Sender : env:1* Now : 0.0000* Parameter(s) : `hello', env:1* DECISION Value: false* OUTPUT of Message to env:1* Parameter(s) : `hello', env:1* OUTPUT of Display to env:1* Parameter(s) : `hello'*** NEXTSTATE idleCommand : output-via MessageParameter 1 (charstring) : `hello'Parameter 2 (pid) : PhonePr:1Channel name :Signal Message was sent to PhonePr:1 from env:1Process scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : Message* Sender : env:1* Now : 0.0000* Parameter(s) : `hello', PhonePr:1* DECISION Value: true* OUTPUT of Display to env:1* Parameter(s) : `hello'*** NEXTSTATE idleCommand : output-via TerminateParameter 1 (pid) : envChannel name :Signal Terminate was sent to PhonePr:1 from env:1Process scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : Terminate* Sender : env:1* Now : 0.0000* Parameter(s) : env:1* DECISION Value: false* OUTPUT of Terminate to env:1* Parameter(s) : env:1* TASK HaltCommand : set-trace 6Default trace set to 6Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : start state* Now : 0.0000*** NEXTSTATE idleCommand : output-via TerminateParameter 1 (pid) : PhonePr:1Channel name :Signal Terminate was sent to PhonePr:1 from env:1Process scope : PhonePr:1Command : next-transition*** TRANSITION START* PId : PhonePr:1* State : idle* Input : Terminate* Sender : env:1* Now : 0.0000* Parameter(s) : PhonePr:1* DECISION Value: true* TASK HaltBy running the system with the SDL monitor, as in the examples above, you may debug the system at the SDL level. The overall behavior of the system can thus be tested.
It is possible to start two instances of the simulation and have the simulators communicate with each other. Then Message and Terminate signals sent to the environment in one of the simulations will appear as signals coming from the environment in the other.
Do not forget the monitor command Start-SDL-Env to make the simulation programs start communicating.
The Environment
In the environment functions we use the socket facility in UNIX to implement the communication between the executing programs. In the current example, the implementation is developed for SunOS 5.
To simplify the example we assume that each instance of the application is started in a window of its own (a shell tool window under for instance X Windows, where UNIX commands can be entered). This means that we will have no problems with the interpretation of stdin and stdout in the programs.
The name of the socket for incoming messages for a certain instance of the application will be the string "Phone" concatenated with the UNIX process number for the current program. The socket will be created in the directory /tmp. Each application instance will print this number during the initialization and will then ask for the process number of the application instance where it should send its messages. You have to enter these numbers in such a way as to form a ring among the applications.
The Environment Functions
The environment functions, which may be found in the file PhoneEnv.c, are shown in section Appendix D: The Environment Functions. The file is developed according to the structure discussed in the previous part of this chapter and uses the system interface header file generated from the SDL system.
As the PhoneEnv.c file includes scttypes.h and uses some C macros, it should be compiled using the same compiler options as the C file for the SDL system. For information about how to extend the generated make file to handle also non-generated files, please see Makefile Options.
In the code for the environment functions a number of UNIX functions are used. Their basic behavior is described below. For any details please see the UNIX manuals available from Sun Microsystems.
If we now look at the code for the environment functions (see Appendix D: The Environment Functions), we see that xInitEnv mainly performs the following actions:
- It creates two unnamed sockets, one for message in (Connection_Socket) and one for messages out (Out_Socket).
- It binds Connection_Socket to the file system (in the /tmp directory) and starts listen for connections.
- It prints its UNIX process number.
- It reads the UNIX process number of the process where to send messages.
- It attempts to connect to the socket of the process where to send messages.
- It accepts the connection from the process that will send messages here.
In xCloseEnv the created sockets are closed and removed.
The xInEnv and xOutEnv functions follow the guidelines for these functions given in the reference section. In xInEnv the select function is used to determine if any messages are ready to be received from the terminal (stdin) or from the incoming socket. An available message is then read and the information is converted to an SDL signal, which is sent to the SDL system using the SDL_Output function. In xOutEnv a test on the NameNode in the signal is used to determine the signal type. Depending on the signal type the appropriate information is written either on the outgoing socket or on the terminal (stdout).
Debugging
The first part of the debugging activity is, of course, when the SDL system is simulated and examined through the monitor system. Now we also want to include the environment functions during debugging. The intention of the library ApplicationDebug is to use the monitor and the environment functions together.
When the environment functions (xInEnv) read information from the keyboard there is, however, a problem in using xInEnv together with the monitor. In our system, for instance, a line typed on the keyboard may either be a monitor command or a line typed to the SDL system. As both the monitor and xInEnv are polling for lines from stdin, the interpretation of a typed line depends on which one first finds the line.
A better way is to eliminate this indeterministic behavior by not polling for typed lines in xInEnv. Instead, you may use the monitor command:
Output-Via TermInput 'the line'to simulate a line typed on the keyboard. In this way all the other parts of the environment functions can be tested under the monitor. If you enclose the sections in xInEnv handling keyboard polling between #ifndef XMONITOR and #endif this code is removed when the monitor is used; that is if the library ApplicationDebug is used (see the code for xInEnv in Appendix D: The Environment Functions).
A C source code debugger is of course also useful when debugging the environment functions. The initialization phase, xInitEnv, is probably the most difficult part to get working correctly in our system. All the source code for this function is available, and a C debugger can be used.
While debugging generated code from SDL at the C level, it is always easy to find the currently executing SDL symbol, by using the SDT references (see Syntax) in the C code and the Go To Source menu choice in the Edit menu in the Organizer. For more details please see Go To Source.
Running the Application
To have an application of the Phone system you now only need to make a new executing program with the library Application.
When you run the Phone system, start the program from two (or more) shell tools (on UNIX). Each instance of the program will then print:
My Pid: 2311Connect me to:You should answer these questions in such a way that a ring is formed by the programs. When the initialization is completed for a program it prints:
******** Welcome to SDT Phone System ********phone ->The program is now ready to receive lines printed on the keyboard and messages sent from other programs. A Display signal received from another program is printed as follows:
display -> the line received in Display signalWhere to Find the Example
All files concerning this example may be found in the directory:
<installation directory>/sdt/examples/phoneUse these files if you only want to look at the source files and if you are using a Sun workstation you could try the executing versions of the program. Otherwise you should copy the files to one of your own directories. Please be sure not to change the original files.
In the directory you will find the following files:
Phone.sdt Phone.ssy PhoneBl.sbk PhonePr.spr phone.pr phone.c phone.ifc PhoneEnv.c Phone.solaris.m
http://www.ibm.com/rational |
![]() |
![]() |
![]() |
![]() |