A Real-Time Data Plotting Program

How to program using the Qt windowing system in X.
Architectural Requirements

In order to provide an acceptable user interface, rtp must quickly respond to GUI events (i.e., mouse events, etc.) at all times. This requirement would be easily met if all program activity were directed by GUI events. For example, an interactive drawing program is entirely GUI-driven, so its only responsibility is to execute relatively short sequences of code in response to GUI events.

rtp's architecture is complicated by two additional requirements, beyond the snappy GUI response. It must quickly update when new data points are available on STDIN. This feature is what differentiates rtp from other plot programs, such as gnuplot. It must also deal with the fact that rendering the data set often takes more time than is acceptable for a GUI delay. This precludes the use of a simple function call to render the whole plot.

Multiplexing Tasks

Fundamentally, there are three “tasks” that rtp must multiplex, listed below from highest to lowest priority:

  1. Respond quickly to GUI events. These events come as data from the X server on a socket.

  2. Read data points from STDIN as they become available.

  3. Render the data set into the plot window when it needs updating.

The Qt library provides mechanisms that support this processing structure. The first mechanism is the QSocketNotifier class. When we create a QSocketNotifier object, we pass it the file descriptor of interest. (The fancy name QSocketNotifier made me think the class was all tied in with network sockets, when in reality it can work with most any file descriptor.) In the case of rtp, this is the STDIN file descriptor (STDIN_FILENO). We then connect QSocketNotifier's activated signal to a particular slot that deals with new data.

The second mechanism is the QTimer class. This class is provided to support regularly scheduled background processing, as well as single-shot timed events. The Qt documentation tells us that by setting up a QTimer object with zero timeout, we can cause a function to be called whenever there are no events to process. Again, the mechanisms for connecting the QTimer to the actual function that does the background processing are signals and slots.

Figure 2. rtp Control Flow and Data Processing


Figure 2 illustrates rtp's control flow and data processing scheme. The Qt event loop is the control center for the application. It calls functions in the rtp application as events occur. Each arrow in the diagram represents a call into a function or library. Note that only the functions which have names starting with PlotWindow or RtpRender are actual rtp code. The rtp functions consist of X event callbacks (such as PlotWindow::paintEvent and friends), the QSocketNotifier callback (PlotWindow::slotStdinAwake) and the QTimer callback (RtpRender::slotWorkAwhile).

XLib is the lowest-level C library provided as an interface to an X server across a byte-stream socket. It manages both the input side of the socket, which provides events, and the output side which sends requests to the server. (Note that Figure 2 shows only the input side.) XLib also provides certain performance optimizations, such as filtering redundant events and delaying requests in an internal queue in order to group requests in large data blocks for efficient socket usage. For details, see Adrian Nye's classic XLib book in Resources.

The POSIX select system call is commonly used by applications that service more than one file descriptor (socket) in a single thread. select is used by applications, such as rtp, that must respond to data on any of several file descriptors and do not wish to waste CPU time by polling. Additionally, Qt uses select's timeout function to start QTimer-scheduled functions.

The select call in the Qt library is the only place (to my knowledge) where the rtp process can block. For newcomers to systems programming, I should explain what “blocking” means. A multitasking operating system such as Linux must be able to multiplex the execution of a large number of programs on a smaller number of processors. By trapping interrupts, Linux switches the processor(s) among running programs in a certain order. This makes it impossible for a single program to lock the system by entering an infinite loop.

Because Linux has pre-emptive multitasking, rtp could enter an infinite loop waiting for either an X event or a data point on STDIN without locking the system. However, the CPU time spent in this loop would unnecessarily degrade the performance of the rest of the executing programs. Therefore, most calls into the kernel for I/O will “block” the executing program until the I/O is complete. The program will be removed from the set of programs run by the CPU. Once the I/O is done, the program is marked as “runnable” and will re-enter the kernel's run queue to be switched in and out of the CPU along with other runnable programs.

select is Qt's way of saying, “I have nothing to do until an X event is available, an I/O event occurs on one of the QSocketNotifier objects, or a timeout from one of the QTimer objects expires.” From Qt's point of view, select waits for one of these events to occur, then returns.

The Qt documentation clearly describes how to use QSocketNotifier and QTimer to hook into select. However, it does not fully describe the priority levels of X events vs. other socket events vs. timer events. In writing a program such as rtp, it is important to understand these details, because the program's performance greatly depends on them.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

bad link

Anonymous's picture
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix