Channels ▼


The Data Distribution Service for Real-Time Systems: Part 1

DDS In a Nutshell

To explain DDS I will take advantage of a running example that is simple and generic enough that you should easily relate to it. I will describe the example in this article and then use it to explain the various DDS features throughout the series. To ensure that you can experiment with what I'll be presenting in the various article all examples will be based on OpenSplice DDS [4], an Open Source DDS implementation, and will use the upcoming ISO C++ DDS API available via the SimD (Simple Dds) [5] Open Source project. The source code for the examples will also be available as part of the SimD distribution.

The example that I will use is the temperature monitoring and control system for a very large building, where each floor of the building has several rooms, each of which is equipped with a set of temperature and humidity sensors and one or more conditioners. The application is supposed to perform both monitoring for all the elements in the building as well as temperature and humidity control for each of the various rooms.

This application is a typical distributed monitoring and control application in which you have data telemetry from several sensors distributed over some spatial location and you also have the control action that has to be applied to the actuators -- our conditioners.

Now that we've created a task for you to solve, let's see what DDS has to offer.

Figure 2: The DDS Global Data Space

The key abstraction at the foundation of DDS is a fully distributed Global Data Space (GDS). It is important to remark that the DDS specification requires the implementation of the Global Data Space to be fully distributed to avoid the introduction of single point of failure or single point of bottleneck. Publishers and Subscribers can join or leave the GDS at any point in time as they are dynamically discovered. The dynamic discovery of Publisher and Subscribers is performed by the GDS and does not rely on any kind of centralized registry such as those found in other pub/sub technologies such as JMS. Finally, I should mention that the GDS also discovers application defined data types and propagates them as part of the discovery process.

In essence, the presence of a GDS equipped with dynamic discovery means that when you deploy a system, you don't have to configure anything. Everything will be automatically discovered and data will begin to flow. Moreover, since the Global Data Space GDS is fully distributed you don't have to fear the crash of some server inducing unknown consequences on the system availability -- in DDS there is no single point of failure, although applications can crash and restart, or connect/disconnect, the system as a whole continues to run.

I've evoked several times this vision of the data flowing from Publishers to Subscribers. In DDS this data is called a "Topic" and represents the unit of information that can be produced or consumed. A Topic is defined as a triad composed of by a type, a unique name, and a set of Quality of Service (QoS) policies which, as I'll explain in great details later in this series, are used to control the non-functional properties associated with the Topic. For the time being it is enough to say that if QoS are not explicitly set, then the DDS implementation will use some defaults prescribed by the standard.

Topic Types can be represented with the subset of the OMG IDL [6] standard that defines struct types, with the limitations that Any-types are not supported. If you are not familiar with the IDL standard you should not worry as essentially, it is safe for you to think that Topic Types are defined with "C-like" structures whose attributes can be primitive types, such as short, long, float, string, etc., arrays, sequences, union and enumerations. Nesting of structures is also allowed. On the other hand, If you are familiar with IDL I am sure you are now wondering how DDS relates to CORBA. The only things that DDS has in common with CORBA is that it uses a subset of IDL; other than this, CORBA and DDS are two completely different Standards and two completely different and complementary technologies.

Now, getting back to our temperature control application, you might want to define topics representing the reading of temperature sensors, the conditioners and perhaps the rooms in which the temperature sensors and the conditioner are installed. Listing 1 provides an example of how you might define the topic type for the temperature sensor.

enum TempScale {

struct TempSensorType {
   short id;
   float temp;
   float hum;
   TempScale scale;
#pragma keylist TempSensorType id

Listing 1: IDL Definition for the TempSensorType

As Listing 1 reveals, IDL structures really look like C/C++ structures, as a result learning to write Topic Types is usually effortless for most programmers. If you are a "detail-oriented" person you'll have noticed that the Listing 1 also includes a suspicious #pragma keylist directive. This directive is used to specify keys. The TempSensorType is specified to have a single key represented by the sensor ID (id) attribute. At runtime, each key value will identify a specific stream of data, more precisely, in DDS we say that each keyvalue identifies a Topic instance. For each instance it is possible for you to observe the life-cycle and learn about interesting transitions such as when it first appeared in the system, or when it was disposed. Keys, along with identifying instances, are also used to capture data relationships as you would in traditional entity relationship modeling. Keys can be made up by an arbitrary number of attributes, some of which could also be defined in nested structures. Once defined the topic type, you can programmatically register a DDS topic using the DDS API by simply instantiating a Topic class with proper type and name:

dds::Topic< TempSensorType> tsTopic("TempSensorTopic");

Now that you have seen how to specify topics it is time to explore how you can make this Topics flow between Publishers and Subscribers. DDS uses the specification of user-defined Topic Types to generate efficient encoding and decoding routines as well as strongly typed DataReaders and DataWriters.

Creating a DataReader or a DataWriter is pretty straightforward as it simply requires to construct an object by instantiating a template class with the Topic Type and passing by the desired Topic object. After you've created a DataReader for your "TempSensorTopic" you are ready to read the data produced by temperature sensors distributed in your system. Likewise after you've created a DataWriter for your "TempSensorTopic" you are ready to write (publish) data. Listings 2 and 3 show the steps required to do so.

If you look a bit closer to Listing 3, you'll see that our first DDS application is using polling to read data out of DDS every second. A sleep is used to avoid spinning in the loop to fast since the DDS read is non-blocking and returns right away if there is no data available. Although polling is a good way to write your first DDS examples it is good to know that DDS supports two ways for informing your application of data availability, listeners and waitsets. Listeners can be registered with readers for receiving notification of data availability as well as several other interesting status changes such as violation in QoS. Waitsets, which are modeled after the Unix-style select call, can be used for waiting the happening of interesting events, one of which could be the availability of data. I will detail these coordination mechanism later on in this series.

I think that looking at this code you'll be a bit puzzled since the data reader and the data writer are completely decoupled. It is not clear where they are writing data to or reading it from, how they are finding about each other and so on.

 * DataWriter

dds::Topic< TempSensorType> tsTopic("TempSensorTopic");
// Create a Publisher connected to the proper partition
// Create a DataWriter
dds::pub::DataWriter< TempSensorType> dw(tsTopic);

TempSensorType ts = {1, 26.0F, 70.0F, CELSIUS};
// Write Data

Listing 2: Writing Data

This is the DDS magic! As I had explained in the very beginning of this article DDS is equipped with dynamic discovery of both participants as well as userdefined data types. Thus it is DDS that discovers data produces and consumers and takes care of matching them. My strongest recommendation is that you try to compile the code examples available with SimD under demo/ddj-series/01 and run them on your machine or even better on a couple of machines. Try running one writer and several readers. Then try adding more writers and see what happens. Also experiment with arbitrary killing (meaning kill -9) readers/writers and restarting them. This way you'll see the dynamic discovery in action.

* DataReader
dds::Topic< TempSensorType> tsTopic("TempSensorTopic");
// Create a DataReader
dds::sub::DataReader< TempSensorType> dr(tsTopic);
dds::sub::SampleInfoSeq info;
TempSensorSeq data;
while (true) {, info);
   for (int i =0; i < data.length(); ++i)
   std::cout < <  data[i] < <  std::endl;

Listing 3: Reading Data

Concluding Remarks

In this first article of the DDS series I've explained the abstraction behind DDS, and introduced some of its foundational concepts. I've also shown you how to write your first DDS applications that distributes temperature sensors values over a distributed system. This was an effort taking less less than 15 lines of code in total, remarkable, isn't it? In the upcoming articles I introduce you to more advanced concepts provided by DDS and by the end of the series you should be able to use all the DDS features to create sophisticated real-time publish/subscribe applications.



[2] OMG. ‚Data Distribution Service for Real-Time Systems Specification. DDS

[3] OMG. Data Distribution Ser vice Interoperability Wire-Protocol Specification. DDSI v2.1

[4] OpenSplice DDS

[5] New ISO C++ DDS API Reference Implementation

[6] Common Object Request Broker Architecture (CORBA/IIOP) v3.1

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.