Reusing DDS Entities
If multiple game objects subscribe or publish to DDS, entities should be reused if possible in order to reduce the resource usage and make it easier to scale. For example, there should only be one domain participant per domain. Usually, an application uses one domain and therefore one domain participant. Having a single domain participant not only reduces the amount of resources needed as each domain participant creates its own receive threads; it also reduces the amount of network traffic and discovery time. Since each domain participant needs to be discovered in a DDS network, having fewer domain participants reduces the amount of discovery traffic.
Let’s go back to the shape.cpp instructions. The previous example started with creating a domain participant as follows:
dds::domain::DomainParticipant participant = dds::domain::DomainParticipant(DomainID);
Instead of creating a domain participant, we will first check to see if we already have one. If so, we use the existing one. The code changes as follows:
/* Let’s see if a domain participant already exists */
dds::domain::DomainParticipant participant = dds::domain::find(DomainID);
/* If not create one */
if (participant == dds::core::null)
{
participant = dds::domain::DomainParticipant(DomainID);
}
In order to use the find function, the header file rti/domain/find.hpp needs to be included.
Each participant has an implicit subscriber, so the call to get the subscriber can stay as is. Next is the topic. Instead of creating the topic, we will check if it already exists, and if it does not, it will be created.
/* Find the topic */
auto topic = dds::topic::find<dds::topic::Topic<dds::core::xtypes::DynamicData>>
(participant, TCHAR_TO_UTF8(*TopicName));
/* If the topic doesn’t exist create it */
if (topic == dds::core::null)
{
topic = dds::topic::Topic<dds::core::xtypes::DynamicData>(participant,
TCHAR_TO_UTF8(*TopicName), myType);
}
The reader is different as there can potentially be multiple readers for the same topic. Therefore, the find functions for data readers returns a list of readers. Since the same reader is being reused, the list should not be larger than one. However, if it is, we just use the first reader from the list.
/* List of readers returned by the find function */
std::vector<dds::sub::DataReader<dds::core::xtypes::DynamicData> > readers;
/* Get the list of readers */
int reader_count = dds::sub::find<dds::sub::DataReader<dds::core::xtypes::DynamicData> >(
subscriber,
TCHAR_TO_UTF8(*TopicName),
std::back_inserter(readers));
/* All we need is at least one reader. If there are multiple let’s use the first one returned.
If no readers are found we create one
*/
if (reader_count)
{
reader = readers[0];
}
else
{
reader = dds::sub::DataReader<dds::core::xtypes::DynamicData>(subscriber, topic);
}
Now if we run the same Unreal Engine configuration as before and look at Admin Console, it will show just one domain participant and one reader for circle and square.
Next, add another square and make it a green square.
Set the mesh to a cube and the material to green.
If you are publishing green and blue squares as well as a red circle, you will see all 3 objects move around.
If you now check Admin Console, you will notice that the DDS entities for the Unreal Engine applications have not changed. There will still be one participant, one subscriber, and a circle and square reader. Since both squares are using the same reader with different query conditions, no additional DDS instance needs to be created to support multiple instances.
Module 8 Demo:
This video covers the steps for Module 8.