Topic Keys, Instances, and Samples
Each Topic comes with an associated key-set. This key-set might be empty or it can include an arbitrary number of attributes defined by the Topic Type. There are no limitations on the number, kind, or level of nesting, of attributes used to establish the key.
enum TemperatureScale {
CELSIUS,
KELVIN,
FARENHEIT
};
struct KeylessTempSensorType {
short id;
float temp;
float hum;
TemperatureScale scale;
};
#pragma keylist KeylessTempSensorType
struct TempSensorType {
short id;
float temp;
float hum;
TemperatureScale scale;
};
#pragma keylist TempSensorType id
Returning to our running example, the temperature control and monitoring system, we could define a keyless variant of the TempSensorType defined in the first installment. Listing 1 shows TempSensorType with the id attribute defined as its key, along with the KeylessTempSensorType showing-off an empty key-set as defined in its #pragma keylist directive.
If we create two topics associated with the types declared in Listing 1 what would be the exact difference between them?
dds::Topic<KeylessTempSensorType>kltsTopic("KLTempSensorTopic");
dds::Topic<TempSensorType> tsTopic("TempSensorTopic");
The main difference between these two topics is their number of instances. Keyless topics have only once instance, thus can be thought as singletons. Keyed topics have once instance per key-value. Making a parallel with classes in object-oriented programming languages, you can think of a Topic as defining a class whose instances are created for each unique value of the topic keys. Thus if the topic has no keys you get a singleton.
Topic instances are runtime entities for which DDS keeps track of whether (1) there are any live writers, (2) the instance has appeared in the system for the first time, and (3) the instance has been disposed -- meaning explicitly removed from the system. Topic instances impact the organization of data on the reader side as well as the memory usage. Furthermore, there are some QoS that apply at an instance-level.
Let me illustrate what happens when you write a keyless topic versus a keyed topic. If we write a sample for the KLSensorTopic this is going to modify the value for exactly the same instance, the singleton, regardless of the content of the sample. On the other hand, each sample you write for the TempSensorTopic will modify the value of a specific topic instance, depending on the value of the key attributes, the id in our example.
Thus, the code below is writing two samples for the same instance, as shown in Figure 1.
dds::DataWriter<KeylessTempSensorType> kltsdw(kltsTopic);
TempSensorType ts = {1, 26.0F, 70.0F, CELSIUS};
secdw.write(ts);
ts = {2, 26.0F, 70.0F, CELSIUS};
secdw.write(ts);
These two samples will be posted in the same reader queue; the queue associated with the singleton instance, as shown in Figure 1.
If we write the same samples for the TempSensorTopic, the end result is quite different. The two samples written in the code fragment below have two different id values, respectively 1 and 2, as a result they are referring to two different instances.
dds::DataWriter<EventCountType> ecdw(ecTopic);
TempSensorType ts = {1, 26.0F, 70.0F, CELSIUS};
secdw.write(ts);
ts = {2, 26.0F, 70.0F, CELSIUS};
secdw.write(ts);
In this case the reader will see these two samples posted into two different queues, as represented in Figure 2, one queue for each instance.
In summary, you should think of Topics as classes in an object-oriented language and understand that each unique key-value identifies an instance. The lifecycle of topic instances is managed by DDS and to each topic instance are associated memory resources, you can think of it as a queue on the reader side.
Keys identify specific data streams within a Topic. Thus, in our running example, each id value will identify a specific temperature sensor. Differently from many other pub/sub technologies, DDS allows you to exploit keys to automatic demultiplex different streams of data. Furthermore, since each temperature sensor will be representing an instance of the TempSensorTopic you'll be able to track the lifecycle of the sensor by tracking the lifecycle of its associated instance. You can detect when a new sensor is added into the system, just because it will introduce a new instance, you can detect when a sensor has failed, thanks to the fact that DDS can inform you when there are no more writers for a specific instance. You can even detect when a sensor has crashed and then recovered thanks to some information about the state transition that are provided by DDS.
Finally, before setting to rest DDS instances, I want to underline that DDS subscriptions concerns Topics. As a result when subscribing to a topic, you'll receive all the instances produced for that topic. In some cases this is not desirable and some scoping actions are necessary. Let's see then what DDS has to offer.


