File builtin_readers.hpp

File List > astutedds > dcps > builtin_readers.hpp

Go to the documentation of this file

//
// Copyright (c) 2026, Astute Systems PTY LTD
//
// This file is part of the Astute DDS developed by Astute Systems.
//
// See the commercial LICENSE file in the project root for full license details.
//
// @file builtin_readers.hpp
// @brief Typed DDS built-in-topic DataReaders (DDS 1.4 §2.2.5, §A.12)
//
// Exposes the four DDS built-in DataReaders reachable through
// DomainParticipant::get_builtin_subscriber() — one per built-in topic:
//
//   Topic name       PSM type                             Source
//   -------------    ---------------------------------    -------------------------
//   DCPSParticipant  ParticipantBuiltinTopicData          SPDP participant cache
//   DCPSTopic        TopicBuiltinTopicData                SEDP DCPSTopic cache (§8.5.4.2)
//   DCPSPublication  PublicationBuiltinTopicData          SEDP DCPSPublication cache
//   DCPSSubscription SubscriptionBuiltinTopicData         SEDP DCPSSubscription cache
//
// Each reader is a lightweight snapshot view over the local participant's
// discovery cache.  read() returns everything currently discovered.
// take() marks records as consumed (by BuiltinTopicKey_t) so subsequent
// take() calls only surface newly-arrived entries.  A background timer
// or WaitSet integration is intentionally NOT wired into this phase — the
// spec permits polling semantics and every accessor is thread-safe.
//
// Not exposed by these readers in this phase:
//   - History/QoS filtering — the built-in reader QoS is fixed (KEEP_LAST 1,
//     RELIABLE, TRANSIENT_LOCAL) but only the semantics matter here.
//   - StatusCondition / on_data_available.  Follow-up work.
//
// See DDS 1.4 §2.2.5 (Built-in Topics) and §A.12 (mandatory feature).
//

#ifndef ASTUTEDDS_DCPS_BUILTIN_READERS_HPP
#define ASTUTEDDS_DCPS_BUILTIN_READERS_HPP

#include <astutedds/dcps/builtin_topic_data.hpp>
#include <astutedds/dcps/dds_psm_types.hpp>

#include <cstdint>
#include <set>
#include <string>
#include <vector>
#include <algorithm>

namespace astutedds::dcps
{
    class DomainParticipant;
    struct SampleInfo;

    struct BuiltinTopicKeyLess
    {
        bool operator()(const BuiltinTopicKey_t& a, const BuiltinTopicKey_t& b) const noexcept
        {
            return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end());
        }
    };

    class BuiltinReaderBase
    {
    public:
        explicit BuiltinReaderBase(DomainParticipant* participant) noexcept
            : participant_(participant) {}

        DomainParticipant* participant() const noexcept { return participant_; }

        void reset() noexcept { taken_.clear(); }

    protected:
        DomainParticipant* participant_{nullptr};
        std::set<BuiltinTopicKey_t, BuiltinTopicKeyLess> taken_;
    };

    class ParticipantBuiltinReader final : public BuiltinReaderBase
    {
    public:
        using BuiltinReaderBase::BuiltinReaderBase;

        ReturnCode_t read(std::vector<ParticipantBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos) const;

        ReturnCode_t take(std::vector<ParticipantBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos);
    };

    class TopicBuiltinReader final : public BuiltinReaderBase
    {
    public:
        using BuiltinReaderBase::BuiltinReaderBase;

        ReturnCode_t read(std::vector<TopicBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos) const;
        ReturnCode_t take(std::vector<TopicBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos);
    };

    class PublicationBuiltinReader final : public BuiltinReaderBase
    {
    public:
        using BuiltinReaderBase::BuiltinReaderBase;

        ReturnCode_t read(std::vector<PublicationBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos) const;
        ReturnCode_t take(std::vector<PublicationBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos);
    };

    class SubscriptionBuiltinReader final : public BuiltinReaderBase
    {
    public:
        using BuiltinReaderBase::BuiltinReaderBase;

        ReturnCode_t read(std::vector<SubscriptionBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos) const;
        ReturnCode_t take(std::vector<SubscriptionBuiltinTopicData>& data,
                          std::vector<SampleInfo>& infos);
    };

    class BuiltinSubscriber
    {
    public:
        explicit BuiltinSubscriber(DomainParticipant* participant)
            : participant_reader_(participant),
              topic_reader_(participant),
              publication_reader_(participant),
              subscription_reader_(participant) {}

        ParticipantBuiltinReader&  participant_reader()  noexcept { return participant_reader_; }
        TopicBuiltinReader&        topic_reader()        noexcept { return topic_reader_; }
        PublicationBuiltinReader&  publication_reader()  noexcept { return publication_reader_; }
        SubscriptionBuiltinReader& subscription_reader() noexcept { return subscription_reader_; }

        void* lookup_datareader(const std::string& topic_name) noexcept
        {
            if (topic_name == "DCPSParticipant")  return &participant_reader_;
            if (topic_name == "DCPSTopic")        return &topic_reader_;
            if (topic_name == "DCPSPublication")  return &publication_reader_;
            if (topic_name == "DCPSSubscription") return &subscription_reader_;
            return nullptr;
        }

    private:
        ParticipantBuiltinReader  participant_reader_;
        TopicBuiltinReader        topic_reader_;
        PublicationBuiltinReader  publication_reader_;
        SubscriptionBuiltinReader subscription_reader_;
    };

}  // namespace astutedds::dcps

#endif  // ASTUTEDDS_DCPS_BUILTIN_READERS_HPP