Never Block in a Listener Callback

You should never block in a listener callback.  There are many negative consequences of blocking in a listener callback:

  • You may lose data for the DataReader the listener is installed on, because the receive thread is not removing it from the socket buffer and it gets overwritten
  • You may receive strictly reliable data with a delay, because the receive thread is not removing it from the socket buffer and if it gets overwritten it must be re-sent
  • You may lose or delay data for other DataReaders, because by default all DataReaders created with the same DomainParticipant share the same threads.
  • You may not be notified of periodic events on time

By default, RTI Connext DDS creates very few threads to use to receive data and only a single thread to handle periodic events.  If you create a listener attached to an entity, that listener is being notified about events within one of RTI Connext DDS’s threads.

RTI Connext DDS creates the following threads by default that can call back your listener:

  • One event thread that handles all periodic processing, such as checking for missed deadlines.  If you use a listener for periodic events such as deadline notifications and liveliness notifications, the corresponding callbacks will be called from the event thread.
  • Three discovery threads:  One unicast receive thread to handle UDPv4 discovery, one multicast receive thread to handle UDPv4 discovery, one shared memory receive thread to handle shared memory discovery.  If you install a listener for discovery data, your on_data_available will be called back from one of the discovery receive threads.
  • One unicast receive thread to handle UDPv4 user data.
  • One receive thread to handle user data over the built-in shared memory transport.
  • When additional transports are installed, or when you enable a DataReader to use multicast additional threads are created.

Notice that by default RTI Connext DDS creates threads for individual transports, not for each DataReader.  This means that if you block in a listener callback when receiving data for one DataReader, not only is that DataReader potentially losing data, but all of your other DataReaders may be losing data.

If you need to make a blocking call when data is available, or when another event occurs, use a WaitSet to receive the notification.

Here are examples of using WaitSets for notifications: