RTI Connext DDS Micro  Version 2.4.11
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Threading Model

This user guide explains the threading model and use of mutexes in RTI Connext DDS Micro.

Introduction

This document describes the threading model, the use of critical sections, and how to configure thread parameters in RTI Connext DDS Micro. Please note that the information contained in this document applies to application development using RTI Connext DDS Micro. For information regarding porting the RTI Connext DDS Micro thread API to a new OS, please refer to Porting RTI Connext DDS Micro.

Architectural Overview

RTI Connext DDS Micro consists of a core library and a number of components. The core library provides a porting layer, frequently used data-structures and abstractions, and the DDS API. Components provide additional functionality such as UDP communication, DDS discovery plugins, DDS history caches, etc.

   +-------+                                      \ 
   | DDS_C |                                       }  C API
   +-------+                                      /
      
   +-------+ +-------+ +------+ +------+          \
   | DPSE  | | DPDE  | | WHSM | | RHSM |          |
   +-------+ +-------+ +------+ +------+          |
   +-------+ +-------+ +------+ +------+ +-----+   } Optional components
   | LOOP  | | UDP(*)| | RTPS | | DRI  | | DWI |  |  (platform independent)
   +-------+ +-------+ +------+ +------+ +-----+  |      
                                                  /
                                                  
   +-------+ +-------+ +------+ +------+          \  Core Services (always
   | REDA  | |  CDR  | | DB   | | RT   |           } present, platform
   +-------+ +-------+ +------+ +------+          /  independent) 
   
   +-----------------------------------+          \
   |               OSAPI               |           } Platform dependent module
   +-----------------------------------+          /                                       

   (*) The UDP transport relies on a BSD socket API 

Threading Model

RTI Connext DDS Micro is architected in a way that makes it possible to create a port of RTI Connext DDS Micro that uses no threads, for example on platforms with no operating system. Thus, the following discussion can only be guaranteed to be true for RTI Connext DDS Micro libraries from RTI.

OSAPI Threads

The RTI Connext DDS Micro OSAPI layer creates one thread per OS process. This thread manages all the RTI Connext DDS Micro timers, such as deadline and liveliness timers. This thread is created by the RTI Connext DDS Micro OSAPI System when the OSAPI_System_initialize() function is called. When the RTI Connext DDS Micro DDS API is used DDS_DomainParticipantFactory_get_instance() calls this function once.

Configuring OSAPI Threads

The timer thread is configured through the OSAPI_SystemProperty structure and any changes must be made before OSAPI_System_initialize() is called. In RTI Connext DDS Micro DomainParticipantFactory_get_instance() calls OSAPI_System_initialize. Thus, if it is necessary to change the system timer thread settings, it must be done before DomainParticipantFactory_get_instance() is called the first time.

Please refer to OSAPI Thread for supported thread options. Note that not all options are supported by all platforms.

struct OSAPI_SystemProperty sys_property = OSAPI_SystemProperty_INITIALIZER;
if (!OSAPI_System_get_property(&sys_property))
{
/* ERROR */
}
/* Please refer to OSAPI_ThreadOptions for possible options */
sys.property.timer_property.thread.options = ....;
/* The stack-size is platform dependent, it is passed directly to the OS */
sys.property.timer_property.thread.stack_size = ....
/* The priority is platform dependent, it is passed directly to the OS */
sys.property.timer_property.thread.priority = ....
if (!OSAPI_System_set_property(&sys_property))
{
/* ERROR */
}

UDP Transport Threads

Of the components that RTI provides, only the UDP component creates threads. The UDP transport creates one receive thread for each unique UDP receive address and port. Thus, three UDP threads are created by default:

\li A multicast receive thread for discovery data (assuming multicast 
    is available and enabled)
\li A unicast receive thread for discovery data
\li A unicast receive thread for user-data

Additional threads may be created depending on the transport configuration for a domain-participant, data-reader and data-writer. The UDP transport creates threads based on the following criteria:

\li Each unique unicast port creates a new thread
\li Each unique multicast address _and_ port creates a new thread

For example, if a data-reader specifies its own multicast receive address a new receive thread will be created.

Configuring UDP Receive Threads

All threads in the UDP transport share the same thread settings. It is important to note that all the UDP properties must be set before the UDP transport is registered. RTI Connext DDS Micro pre-registers the UDP transport with default settings when the DomainParticipantFactory is initialized. To change the UDP thread settings, use the following code.

RT_Registry_T *registry = NULL;
DDS_DomainParticipantFactory *factory = NULL;
struct UDP_InterfaceFactoryProperty *udp_property = NULL;
udp_property = (struct UDP_InterfaceFactoryProperty *)
malloc(sizeof(struct UDP_InterfaceFactoryProperty));
*udp_property = UDP_INTERFACE_FACTORY_PROPERTY_DEFAULT;
if (!RT_Registry_unregister(registry, "_udp", NULL, NULL))
{
/* ERROR */
}
/* Please refer to OSAPI_ThreadOptions for possible options */
udp_property->recv_thread.options = ...;
/* The stack-size is platform dependent, it is passed directly to the OS */
udp_property->recv_thread.stack_size = ....
/* The priority is platform dependent, it is passed directly to the OS */
udp_property->recv_thread.priority = ....
if (!RT_Registry_register(registry, "_udp",
(struct RT_ComponentFactoryProperty*)udp_property,
NULL))
{
/* ERROR */
}

General Thread Configuration

The RTI Connext DDS Micro architecture consists of a number of components and layers, and each layer and component has its own properties. It is important to remember that the layers and components are configured independently of each other, as opposed to configuring everything through DDS. This design makes it possible to relatively easily swap out one part of the library for another.

All threads created based on RTI Connext DDS Micro OSAPI APIs use the same OSAPI_ThreadProperty structure.

Critical Sections

RTI Connext DDS Micro may create multiple threads, but from an application point of view there is only a single critical section protecting all DDS resources. Note that although RTI Connext DDS Micro may create multiple mutexes, these are used to protect resources in the OSAPI layer and are thus not relevant when using the public DDS APIs.

Calling DDS APIs from listeners

When DDS is executing in a listener it holds a critical section. Thus it is important to return as quickly as possible to avoid stalling network I/O.

There are no deadlock scenarios when calling RTI Connext DDS Micro DDS APIs from a listener. However, there are no checks on whether or not an API call will cause problems, such as deleting a participant when processing data in on_data_available() from a reader within the same participant.


RTI Connext DDS Micro Version 2.4.11 Copyright © Mon Jul 23 2018 Real-Time Innovations, Inc