QNX Persistent Publish/Subscribe Service, Part I

“There are various reasons that software tends to be unwieldy, but a primary one is what I like to call ‘brittleness’…”
    — Jaron Lanier, quoted in an article by Jack Ganssle
“[Roll-your-own] solutions tend to be designed and implemented based on initial connectivity requirements and thus are very brittle when new requirements are introduced. They typically rely on direct, point-to-point connections between communicating applications/components…”
    — Jerry Krasner, from an article on Embedded.com
Brittleness. It’s a word that few people associate with software. But to implement connections between software components, C and C++ developers must often define exact and therefore fragile function prototypes. As a result, a change in one component can necessitate a change in other components. For instance, if a developer needs to change the status information returned by a device driver, they might also need to implement a corresponding change in the human machine interface (HMI).

This tight coupling makes things difficult for many embedded designs, particularly those that combine low-level control with high-level user applications. Take, for example, a realtime system for motor control that uses an HMI based on Adobe Flash. The Flash team may have little, if any, idea as to how to design a realtime system, let alone communicate with it. And the realtime team might have zero experience with Flash. The two teams live in different worlds: how do you bridge the gap?

To address these challenges, QNX Software Systems has introduced a Persistent Publish-Subscribe (PPS) service for embedded systems. Small and extensible, PPS allows developers to build loosely connected systems based on asynchronous publications and notifications. PPS also offers data persistence across reboots.

Creating decoupled designs

PPS provides an object-based system that consists of publishers and subscribers: publishers modify the properties of data objects and the subscribers to those objects receive updates when the objects have been modified.

With PPS, publishing is asynchronous: the subscriber of a service doesn’t have to wait for the publisher. This approach eliminates work for the subscriber process, as it doesn’t have to spawn a new thread to receive information from the publisher, synchronize the return of data with that new thread, or poll for a result.

In fact, the publisher and subscriber don’t have to “know” each other; their only connection is an object that has a meaning and purpose for both of them.

This “decoupling” gives the development team greater flexibility, as they can delay decisions on module connection points and data flow until runtime. Because such decisions don’t have to be hardcoded or directly linked, they can be adapted as situations or requirements evolve; they can even change dynamically as the system runs.

In many ways, PPS is similar to process control systems where the objects are control values updated by hardware or software. Subscribers can be alarm-handling code, displays, and so on. In fact, PPS is well-suited to such systems, as well as to others that have a similar data model.

Scalable, persistent, and language independent

PPS offers many benefits, including:
  • Loose coupling for scalable design — With PPS, you can easily plug in (or plug out) different publishers or consumers of a data source, without having to create a fine-tuned, highly synchronized API between components.

  • Greater flexibility than conventional IPC — PPS goes beyond the conventional one-to-one relationship between software components. It also supports one-to-many relationships (one publisher, multiple subscribers) and many-to-one relationships (many publishers, one subscriber).

  • Data persistence across reboots — PPS allows data sources to survive a reset, without the need for any special software logic. This state-saving capability, useful for a variety of industrial and automotive environments, is built in: the developer doesn’t have to design or implement any special data failsafe mechanisms to take advantage of it.

  • Language independence — Because PPS leverages the services of standard POSIX file systems, it can work with any programming language or application environment, including C, C++, Java, Adobe Flash, ksh, and others. Components written in completely different languages can intercommunicate, without requiring any special knowledge of one another.

In Part II, I cover a couple of short examples that show how developers can use PPS in industrial and automotive systems.

My colleague Andy Gryc provided invaluable assistance while I was writing this post. The insights are his; any errors are mine.

No comments: