DDS-PSM-Cxx 1.1 RTF Avatar
  1. OMG Issue

DDSPSMC11_ — Listener model breaks API design goal of automatic resource management

  • Key: DDSPSMC11_-95
  • Status: open  
  • Source: Real-Time Innovations ( Alex Campos)
  • Summary:

    The way the C++ PSM modeled listeners has proven problematic. While the whole language binding is designed to provide automatic resource management, listeners break that model. Listeners are assigned to a DDS Entity as a raw pointer and “retain” the Entity.

    Because an Entity with a listener is retained, the user must manually reset the listener to allow its automatic destruction or explicitly close the entity. This defeats the purpose of automatic resource management, forcing users to write exception-safe code or risk “leaking” the resource.

    RTI proposes a change in how listeners are set. In summary:

    1) Listeners are set as std::shared_ptr's. All APIs change to receive a std::shared_ptr<Listener> instead of a Listener*
    2) Listeners no longer retain the entity. (It's the other way around; the Entity keeps a reference to its listener, which ensures the listener is not deleted). 

    Note that an entity can be explicitly retained with the member function retain(), which allows preserving the old behavior quite easily.

    The changes, affecting all dds::core::Entity-derived types, are the following:

    Previous API (usable but deprecated) New API
    Constructor with Listener* argument Constructor with std::shared_ptr<Listener>
    Listener setter: listener(Listener*, StatusMask) Listener setter: set_listener(std::shared_ptr<Listener>, StatusMask)
     (not available) Listener setter with no mask, added for convenience: set_listener(std::shared_ptr<Listener>) // Defaults to all() when the listener is not null or none() when it’s null
    Listener getter: Listener * listener() const  Listener getter: std::shared_ptr<Listener> get_listener() const

    Notice the name change—the overloaded listener is now get_listener/set_listener. A new overload wasn’t possible because the getter would only differ on the return type.

    Implementations that do not support C++11 can offer the old listener model.

    // Previous API:
    MyListener *my_listener = new MyListener();
    reader.listener(my_listener, StatusMask::all());
    // ...
    reader.listener(NULL, StatusMask::none()); // user must reset the listener to destroy entity
    delete my_listener;
    // New API:
    auto my_listener = std::make_shared<MyListener>();
    reader.set_listener(my_listener);// No manual resource management required anymore
    // Or simply:


  • Reported: DDS-PSM-Cxx 1.0b2 — Sun, 14 Jun 2020 19:45 GMT
  • Updated: Mon, 15 Jun 2020 23:32 GMT