A Topic conceptually fits between publications and subscriptions. Each publication channel must be unambiguously identified by the subscriptions in order to receive only the data flow they are interested in, and not data from other publications.

A Topic serves this purpose, allowing publications and subscriptions that share the same Topic to match and start communicating. In that sense, the Topic acts as a description for a data flow.

Keys and Instances

By definition, a Topic is linked to a single data type, so each data sample related to a Topic could be understood as an update on the information described by the data type.

However, it is possible to include a logical separation and have, within the same Topic, several instances referring to the same data type. Thus, the received data sample will be an update for a specific instance of that Topic.

Therefore, a Topic identifies data of a single type, ranging from one single instance to a whole collection of instances of that given type.

The different instances gathered under the same topic are distinguishable by means of one or more data fields that form the key to that data set. The key description has to be indicated to the middleware.

The rule is simple: different data values with the same key value represent successive data samples for the same instance, while different data values with different keys represent different topic instances.

If no key is provided, the data set associated with the Topic is restricted to a single instance.

Please refer to Typesupport for more information about how enable and get key values in Safe DDS.

Instance lifecycle

When reading or taking data from a DataReader (as explained in Accessing received data), a SampleInfo is also returned. This SampleInfo provides additional information about the instance lifecycle. The diagram below shows the state chart of SampleInfo::instance_state and SampleInfo::view_state for a single instance.



TopicQos controls the behavior of the Topic. Internally it contains the following Policy objects:

Safe DDS Usage

In Safe DDS, TopicQos::resource_limits shall be configured in a way that it can hold the sum of all configurations done in the DataReaderQos and DataWriterQos of all the DataReader and DataWriter that will be using the Topic.

Safe DDS Usage

Check Memory management to understand how memory is managed in Safe DDS.


// Construct TopicQos with default values
TopicQos topic_qos{};

// Set DurabilityQosPolicy
topic_qos.durability().kind = DurabilityQosPolicyKind::TRANSIENT_DURABILITY_QOS;

// Set DeadlineQosPolicy
topic_qos.deadline().period = {1, 0};

// Set LivelinessQosPolicy
topic_qos.liveliness().kind = LivelinessQosPolicyKind::AUTOMATIC_LIVELINESS_QOS;
topic_qos.liveliness().lease_duration = {1, 0};

// Set ReliabilityQosPolicy
topic_qos.reliability().kind = ReliabilityQosPolicyKind::BEST_EFFORT_RELIABILITY_QOS;

// Set HistoryQosPolicy
topic_qos.history().kind = HistoryQosPolicyKind::KEEP_LAST_HISTORY_QOS;
topic_qos.history().depth = 10;

// Set ResourceLimitsQosPolicy
topic_qos.resource_limits().max_samples = 1000;
topic_qos.resource_limits().max_instances = 10;
topic_qos.resource_limits().max_samples_per_instance = 3;

// Set TopicAllocationsQosPolicy memory configuration
topic_qos.allocations().observers.preallocated = 10;
topic_qos.allocations().observers.max_elements = 1000;

Topic Listener

TopicListener is an abstract class defining the callbacks that will be triggered in response to state changes on the Topic. By default, all these callbacks are empty and do nothing. Implementations of this class shall override the callbacks that are needed on the application. Callbacks that are not overridden will maintain their empty implementation.

TopicListener has the following callback:

  • TopicListener::on_inconsistent_topic

    A remote Topic is discovered with the same name but different characteristics as another locally created Topic.


class CustomTopicListener : public TopicListener
    void on_inconsistent_topic(
            Topic& /* topic */,
            const InconsistentTopicStatus& /* status */) noexcept override
        std::cout << "Inconsistent topic found" << std::endl;


Create a Topic

A Topic always belongs to a DomainParticipant. Creation of a Topic is done with the DomainParticipant::create_topic member function on the DomainParticipant instance, that acts as a factory for the Topic.

Mandatory arguments are:

  • The name to identify the topic.

  • The name of the registered data type that will be transmitted.

  • The TopicQos describing the behavior of the Topic.

Optional arguments are:

  • A Listener derived from Topic Listener, implementing the callbacks that will be triggered in response to events and state changes on the Topic.

  • A StatusMask that activates or deactivates triggering of individual callbacks on the Topic Listener.

DomainParticipant::create_topic will return a null pointer if there was an error during the operation, e.g. if the provided QoS is not compatible or is not supported. It is advisable to check that the returned value is a valid pointer.


// Definition of a Topic QoS
TopicQos topic_qos{};

// Instantiation of a custom TopicListener
CustomTopicListener topic_listener{};

// Creation of a StatusMask
StatusMask topic_mask = ANY_STATUS_MASK;

// Remove a unwanted status
status_mask_unset(topic_mask, INCONSISTENT_TOPIC_STATUS);

// Define the Topic's name and type
memory::container::StaticString256 topic_name("safedds_topic");
memory::container::StaticString256 type_name("safedds_type");

// Creation of a Topic
Topic* topic = participant->create_topic(

// Check if the Topic was created
if (nullptr == topic)
    std::cout << "Error creating Topic" << std::endl;

Static memory example

In order to create a Topic that does not use any platform allocation a StaticTopic can be instantiated:

Safe DDS Usage

When using Safe DDS Static memory API, any Policy related with PreallocMemoryConfig in TopicQos will be ignored.

constexpr size_t STATIC_TOPIC_MAX_SAMPLES_IN_TOPIC = 100;
constexpr size_t STATIC_TOPIC_MAX_SERIALIZED_SIZE = 1000;
constexpr size_t STATIC_TOPIC_MAX_LOCAL_READERS = 1;