Continues migration with DDS, Common

This commit is contained in:
torsten committed 2026-07-17 12:41:42 +02:00
1 parent 9b15cee841
commit fa48db111e
668 files changed
+111841 -2

No files matched your search

+45
View File
@@ -0,0 +1,45 @@
#
# $Id$
# $HeadURL$
# $Author$
#
ADD_LIBRARY(ddsfts_connext INTERFACE)
TARGET_INCLUDE_DIRECTORIES(ddsfts_connext
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../../
)
TARGET_LINK_LIBRARIES(ddsfts_connext
INTERFACE
RTI::nddscpp2
)
SET(SRCS
${CMAKE_CURRENT_SOURCE_DIR}/connext.h
)
TARGET_SOURCES(ddsfts_connext INTERFACE ${SRCS})
SET(SRCS
generic_fts.h ;# Interface
generic_fts_impl.h ;# Implementation, using internal class GenericFTCInternal
generic_fts_internal.h
generic_fts_internal.cpp
)
NGL_ADD_LIBRARY2(WS AAR SV HLA ddsfts SHARED ${SRCS})
NGL_TARGET_INCLUDE_DIRECTORIES(
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../../
)
NGL_TARGET_LINK_LIBRARIES(ddsfts
PRIVATE
RTI::nddscore
ProjectConfig
ddsQoS
PUBLIC
Qt5::Core
RTI::nddsc
RTI::nddscpp2
ddsgen
ddsfts_connext
)
+502
View File
@@ -0,0 +1,502 @@
#pragma once
#include <dds/core/cond/GuardCondition.hpp>
#include <dds/core/cond/StatusCondition.hpp>
#include <dds/core/cond/WaitSet.hpp>
#include <dds/domain/DomainParticipant.hpp>
#include <dds/pub/DataWriter.hpp>
#include <dds/pub/Publisher.hpp>
#include <dds/sub/DataReader.hpp>
#include <dds/sub/SampleInfo.hpp>
#include <dds/sub/Subscriber.hpp>
#include <dds/topic/ContentFilteredTopic.hpp>
#include <dds/topic/find.hpp>
#include <rti/pub/WriteParams.hpp>
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace connext
{
namespace DebugInfo
{
inline QByteArray toReadable(const rti::core::Guid &guid)
{
const QByteArray str(reinterpret_cast<const char *>(&guid[0]), 16);
return str.toHex();
}
inline QByteArray toReadable(const rti::core::SequenceNumber &seqNo,
const rti::core::Guid &guid)
{
return "SeqNo: " + QByteArray::number(seqNo.value()) +
", Guid-DW: " + toReadable(guid);
}
inline QByteArray toReadable(const rti::core::SampleIdentity &identiy)
{
return toReadable(identiy.sequence_number(), identiy.writer_guid());
}
}
template<typename T>
dds::topic::Topic<T> getTopic(const dds::domain::DomainParticipant &participant,
const std::string &topicName)
{
using DataTopic = dds::topic::Topic<T>;
auto ret = dds::topic::find<DataTopic>(participant, topicName);
if (ret != nullptr)
return ret;
return DataTopic(participant, topicName);
}
template<typename T>
class SampleBase
{
protected:
SampleBase() = default;
virtual ~SampleBase() = default;
public:
void set_data(const T &data)
{
m_data = data;
}
T &data()
{
return m_data;
}
const T &data() const
{
return m_data;
}
protected:
T m_data;
};
template<typename T>
class WriteSample : public SampleBase<T>
{
public:
WriteSample() = default;
void set_info(const rti::pub::WriteParams &info)
{
m_info = info;
}
rti::pub::WriteParams &info()
{
return m_info;
}
const rti::pub::WriteParams &info() const
{
return m_info;
}
private:
rti::pub::WriteParams m_info;
};
template<typename T>
class WriteSampleRef
{
public:
WriteSampleRef()
: m_data_ptr(nullptr)
, m_info_ptr(nullptr)
{}
void set_data(T *data_ptr)
{
m_data_ptr = data_ptr;
}
T &data()
{
return *m_data_ptr;
}
void set_info(rti::pub::WriteParams *info_ptr)
{
m_info_ptr = info_ptr;
}
rti::pub::WriteParams &info()
{
return *m_info_ptr;
}
private:
T *m_data_ptr;
rti::pub::WriteParams *m_info_ptr;
};
template<typename T>
class Sample : public SampleBase<T>
{
public:
Sample() = default;
void set_info(const dds::sub::SampleInfo &info)
{
m_info = info;
}
dds::sub::SampleInfo &info()
{
return m_info;
}
const dds::sub::SampleInfo &info() const
{
return m_info;
}
void set_identity(const rti::core::SampleIdentity &identity)
{
m_identity = identity;
}
const rti::core::SampleIdentity &identity() const
{
return m_identity;
}
private:
dds::sub::SampleInfo m_info;
rti::core::SampleIdentity m_identity;
};
class RequesterParams
{
public:
explicit RequesterParams(const dds::domain::DomainParticipant &participant)
: m_participant(participant)
, m_publisher(nullptr)
, m_subscriber(nullptr)
{}
virtual ~RequesterParams() = default;
const std::string &request_topic_name() const
{
return m_request_topic_name;
}
void request_topic_name(const std::string &request_topic_name)
{
m_request_topic_name = request_topic_name;
}
const std::string &reply_topic_name() const
{
return m_reply_topic_name;
}
void reply_topic_name(const std::string &reply_topic_name)
{
m_reply_topic_name = reply_topic_name;
}
const dds::domain::DomainParticipant &domainParticipant() const
{
return m_participant;
}
const dds::pub::Publisher &publisher() const
{
return m_publisher;
}
void publisher(const dds::pub::Publisher &publisher)
{
m_publisher = publisher;
}
const dds::sub::Subscriber &subscriber() const
{
return m_subscriber;
}
void subscriber(const dds::sub::Subscriber &subscriber)
{
m_subscriber = subscriber;
}
const dds::pub::qos::DataWriterQos &datawriter_qos() const
{
return m_datawriter_qos;
}
void datawriter_qos(const dds::pub::qos::DataWriterQos &datawriter_qos)
{
m_datawriter_qos = datawriter_qos;
}
const dds::sub::qos::DataReaderQos &datareader_qos() const
{
return m_datareader_qos;
}
void datareader_qos(const dds::sub::qos::DataReaderQos &datareader_qos)
{
m_datareader_qos = datareader_qos;
}
protected:
dds::domain::DomainParticipant m_participant;
dds::pub::Publisher m_publisher;
dds::sub::Subscriber m_subscriber;
dds::pub::qos::DataWriterQos m_datawriter_qos;
dds::sub::qos::DataReaderQos m_datareader_qos;
std::string m_request_topic_name;
std::string m_reply_topic_name;
};
template <typename REQUEST, typename REPLY>
class ReplierParams : public RequesterParams
{
public:
using RequesterParams::RequesterParams;
};
template<typename REQUEST, typename REPLY>
class ReplyRequestBase
{
protected:
explicit ReplyRequestBase(const connext::RequesterParams &requesterParams)
: m_requestTopic(getTopic<REQUEST>(requesterParams.domainParticipant(),
requesterParams.request_topic_name()))
, m_replyTopic(getTopic<REPLY>(requesterParams.domainParticipant(),
requesterParams.reply_topic_name()))
{}
virtual ~ReplyRequestBase() = default;
protected:
dds::topic::Topic<REQUEST> m_requestTopic;
dds::topic::Topic<REPLY> m_replyTopic;
};
template<typename REQUEST, typename REPLY>
class Requester final : public ReplyRequestBase<REQUEST, REPLY>
{
public:
explicit Requester(const connext::RequesterParams &requesterParams)
: ReplyRequestBase<REQUEST, REPLY>(requesterParams)
, m_requesterParams(requesterParams)
, m_dataWriter(nullptr)
, m_dataReader(nullptr)
, m_contentFilteredTopic(nullptr)
, m_curInstanceHandle(dds::core::InstanceHandle::nil())
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("connext.requester"))
{}
void create_contentfilter(bool bNewDataWriter)
{
if (!bNewDataWriter && m_contentFilteredTopic != nullptr)
return;
rti::core::policy::DataWriterProtocol dwp;
m_dataWriter.qos() >> dwp;
const rti::core::Guid dwGuid = dwp.virtual_guid();
const QByteArray writerGuid = DebugInfo::toReadable(dwGuid);
const QByteArray filterContent = "@related_sample_identity.writer_guid.value = &hex(" + writerGuid + ")";
if (m_contentFilteredTopic == nullptr)
{
const std::string rtName = ReplyRequestBase<REQUEST, REPLY>::m_replyTopic.name();
const QByteArray filterName(QByteArray::fromRawData(rtName.c_str(), static_cast<int>(rtName.size())) +
QByteArray(" ") + writerGuid);
m_contentFilteredTopic = dds::topic::ContentFilteredTopic<REPLY>(ReplyRequestBase<REQUEST, REPLY>::m_replyTopic,
filterName.data(),
dds::topic::Filter(filterContent.data()));
}
else
{
m_contentFilteredTopic->filter(dds::topic::Filter(filterContent.data()));
}
DEBUG_LOG(m_logger) << "content filter for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< " - related_sample_identity should be: "
<< writerGuid;
}
void send_request(connext::WriteSample<REQUEST> &request)
{
bool bNewDataWriter = false;
if (m_dataWriter == nullptr)
{
m_dataWriter = dds::pub::DataWriter<REQUEST>(m_requesterParams.publisher(),
ReplyRequestBase<REQUEST, REPLY>::m_requestTopic,
m_requesterParams.datawriter_qos());
bNewDataWriter = true;
}
else
{
}
create_contentfilter(bNewDataWriter);
if (m_dataReader == nullptr)
{
m_dataReader = dds::sub::DataReader<REPLY>(m_requesterParams.subscriber(),
m_contentFilteredTopic,
m_requesterParams.datareader_qos());
}
m_curInstanceHandle = m_dataWriter.register_instance(request.data());
request.info().replace_automatic_values(true);
request.info().identity(rti::core::SampleIdentity::automatic());
m_dataWriter->write(request.data(), request.info());
const rti::core::SampleIdentity currentSampleIdentity = request.info().identity();
DEBUG_LOG(m_logger) << "send_request for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", m_currentSampleIdentity: "
<< DebugInfo::toReadable(currentSampleIdentity);
}
bool receive_reply(connext::Sample<REPLY> &reply,
const dds::core::Duration &duration)
{
auto condition(dds::sub::cond::ReadCondition(m_dataReader, dds::sub::status::SampleState::not_read()));
dds::core::cond::WaitSet waitset;
waitset.attach_condition(condition);
bool bRet = false;
while (true)
{
if (m_dataReader->take(reply.data(), reply.info()) && reply.info().valid())
{
DEBUG_LOG(m_logger) << "receive_reply for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", SampleIdentity - original publication virtual: "
<< DebugInfo::toReadable(reply.info()->original_publication_virtual_sample_identity());
DEBUG_LOG(m_logger) << "receive_reply for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", SampleIdentity - related original: "
<< DebugInfo::toReadable(reply.info()->related_original_publication_virtual_sample_identity());
bRet = true;
break;
}
dds::core::cond::WaitSet::ConditionSeq activeConditionsSeq = waitset.wait(duration);
if (activeConditionsSeq.empty())
{
ERROR_LOG(m_logger) << "Bailing out!";
break;
}
}
static const rti::core::SampleFlag irs(rti::core::SampleFlag::intermediate_reply_sequence());
if ((reply.info()->flag() & irs) == 0)
{
if (!m_curInstanceHandle.is_nil())
{
DEBUG_LOG(m_logger) << "Keyed topic - disposing instance: "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name();
m_dataWriter.dispose_instance(m_curInstanceHandle);
}
}
return bRet;
}
dds::pub::DataWriter<REQUEST> get_request_datawriter() const { return m_dataWriter; }
dds::sub::DataReader<REPLY> get_request_datareader() const { return m_dataReader; }
private:
connext::RequesterParams m_requesterParams;
dds::pub::DataWriter<REQUEST> m_dataWriter;
dds::sub::DataReader<REPLY> m_dataReader;
dds::topic::ContentFilteredTopic<REPLY> m_contentFilteredTopic;
dds::core::InstanceHandle m_curInstanceHandle;
NGL::INGLLogger &m_logger;
};
template<typename REQUEST, typename REPLY>
class Replier final : public ReplyRequestBase<REQUEST, REPLY>
{
public:
explicit Replier(const connext::ReplierParams<REQUEST, REPLY> &replierParams)
: ReplyRequestBase<REQUEST, REPLY>(replierParams)
, m_replierParams(replierParams)
, m_dataWriter(dds::pub::DataWriter<REPLY>(replierParams.publisher(),
ReplyRequestBase<REQUEST, REPLY>::m_replyTopic,
replierParams.datawriter_qos()))
, m_dataReader(dds::sub::DataReader<REQUEST>(replierParams.subscriber(),
ReplyRequestBase<REQUEST, REPLY>::m_requestTopic,
replierParams.datareader_qos()))
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("connext.replier"))
{}
void send_reply(connext::WriteSample<REPLY> &reply,
const rti::core::SampleIdentity &identity,
bool bLastSample = true)
{
connext::WriteSampleRef<REPLY> replyRef;
replyRef.set_data(&reply.data());
replyRef.set_info(&reply.info());
return send_reply(replyRef, identity, bLastSample);
}
void send_reply(connext::WriteSampleRef<REPLY> &reply,
const rti::core::SampleIdentity &identity,
bool bLastSample = true)
{
DEBUG_LOG(m_logger) << "send_reply for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", sampleIdentity: " << DebugInfo::toReadable(identity);
rti::core::SampleFlag sf = reply.info().flag();
if (bLastSample)
sf &= ~rti::core::SampleFlag::intermediate_reply_sequence();
else
sf |= rti::core::SampleFlag::intermediate_reply_sequence();
reply.info().flag(sf);
reply.info().related_sample_identity(identity);
DEBUG_LOG(m_logger) << "send_reply for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", related sampleIdentity: " << DebugInfo::toReadable(reply.info().related_sample_identity());
m_dataWriter->write(reply.data(), reply.info());
}
bool receive_request(connext::Sample<REQUEST> &request)
{
if (!m_dataReader->take(request.data(), request.info()))
return false;
if (request.info().valid())
{
DEBUG_LOG(m_logger) << "receive_request for topic "
<< ReplyRequestBase<REQUEST, REPLY>::m_requestTopic.name()
<< ", sampleIdentity publication_virtual_sample_identity: "
<< DebugInfo::toReadable(request.info()->publication_virtual_sample_identity())
<< ", original_publication_virtual_sample_identity: "
<< DebugInfo::toReadable(request.info()->original_publication_virtual_sample_identity())
<< ", related_original_publication_virtual_sample_identity: "
<< DebugInfo::toReadable(request.info()->related_original_publication_virtual_sample_identity())
<< " with timestamp_ " << request.info().source_timestamp().to_millisecs();
request.set_identity(request.info()->original_publication_virtual_sample_identity());
}
return request.info().valid();
}
dds::pub::DataWriter<REPLY> get_request_datawriter() const { return m_dataWriter; }
dds::sub::DataReader<REQUEST> get_request_datareader() const { return m_dataReader; }
private:
connext::ReplierParams<REQUEST, REPLY> m_replierParams;
dds::pub::DataWriter<REPLY> m_dataWriter;
dds::sub::DataReader<REQUEST> m_dataReader;
NGL::INGLLogger &m_logger;
};
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <rti/core/SampleIdentity.hpp>
#include <QVector>
namespace FTS
{
template <typename TOPICTYPE_REQUEST, typename TOPICTYPE_REPLY>
class GenericFts
{
public:
GenericFts() = default;
virtual ~GenericFts() = default;
virtual bool sendReply(const rti::core::SampleIdentity &requestIdentity, const TOPICTYPE_REPLY &replyData) = 0;
virtual bool sendReply(const rti::core::SampleIdentity &requestIdentity, const QVector<TOPICTYPE_REPLY> &replyData) = 0;
};
}
+287
View File
@@ -0,0 +1,287 @@
#pragma once
#include <DDS/Core/core.hpp>
#include "generic_fts_internal.h"
#include "connext.h"
#include <DDS/Generic/wait_set_handler.h>
#include <DDS/Generic/generic_base.h>
#include <DDS/Generic/generic_logger.h>
#include <queue>
#include <type_traits>
#include <typeinfo>
#include <sstream>
#ifndef tr_lts
#define tr_lts(ctx, t) (t)
#endif
namespace FTS
{
template <class C>
class HasStatusFunction
{
template <class T>
static std::true_type testSignature(void (T::*)(const Core::FtReplyState&));
template <class T>
static decltype(testSignature(&T::replyState)) test(std::nullptr_t);
template <class T>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
template<typename GENERIC_FTS>
struct TopicNames;
template<typename TOPICTYPE_REQUEST, typename TOPICTYPE_REPLY, typename DUMMY>
class GenericFtsImpl final : public GenericFts<TOPICTYPE_REQUEST,TOPICTYPE_REPLY>
, public GenericFtsInternal
{
public:
using RequestTopic = TOPICTYPE_REQUEST;
using ReplyTopic = TOPICTYPE_REPLY;
using TopicNameHelper = TopicNames<GenericFtsImpl<RequestTopic, ReplyTopic, DUMMY>>;
private:
using SubscriberCallback = std::function<void(const rti::core::SampleIdentity&, const RequestTopic&)>;
template <typename T = ReplyTopic, typename std::enable_if<HasStatusFunction<T>::value, int>::type = 0>
void sendReplyState(Core::FtReplyState replyState, const rti::core::SampleIdentity &requestSampleIdentity)
{
connext::WriteSample<ReplyTopic> reply;
reply.data().replyState(replyState);
bool bLastTelegram = ((replyState != Core::FtReplyState_def::InProgress) &&
(replyState != Core::FtReplyState_def::NotStarted));
m_replier->send_reply(reply, requestSampleIdentity, bLastTelegram);
}
template <typename T = ReplyTopic, typename std::enable_if<!HasStatusFunction<T>::value, int>::type = 0>
void sendReplyState(Core::FtReplyState, const rti::core::SampleIdentity &)
{
}
template <typename T, typename std::enable_if<HasStatusFunction<T>::value, int>::type = 0>
void setReply(T &data, Core::FtReplyState status)
{
data.replyState(status);
}
template <typename T, typename std::enable_if<!HasStatusFunction<T>::value, int>::type = 0>
void setReply(T &, Core::FtReplyState)
{
}
public:
GenericFtsImpl(const dds::domain::DomainParticipant &domainParticipant,
const dds::pub::Publisher &ddsPublisher,
const dds::sub::Subscriber &ddsSubscriber,
DDSGeneric::WaitSetHandler *wsHandler)
: GenericFts<RequestTopic,ReplyTopic>()
, GenericFtsInternal()
, m_wsHandler(wsHandler)
, m_subscriberCallback(nullptr)
, m_logger(DDS::getLogger(TopicNameHelper::functionTopicName(), DDS::DataType::FUNCTION_TOPIC_SERVER))
{
Q_ASSERT(domainParticipant != nullptr);
Q_ASSERT(ddsPublisher != nullptr);
Q_ASSERT(ddsSubscriber != nullptr);
Q_ASSERT(wsHandler != nullptr);
qRegisterMetaType<RequestTopic> (TopicNameHelper::requestTopicTypeName());
connext::ReplierParams<RequestTopic,ReplyTopic> replierParams(domainParticipant);
replierParams.request_topic_name(TopicNameHelper::requestTopicName());
replierParams.reply_topic_name(TopicNameHelper::replyTopicName());
replierParams.publisher(ddsPublisher);
replierParams.subscriber(ddsSubscriber);
replierParams.datareader_qos(readerQos(m_logger));
replierParams.datawriter_qos(writerQos(m_logger));
m_replier = new connext::Replier<RequestTopic, ReplyTopic>(replierParams);
m_readCondition = new dds::sub::cond::ReadCondition(m_replier->get_request_datareader(), dds::sub::status::SampleState::not_read());
m_wsHandler->attachWaitSet(*m_readCondition, this);
}
~GenericFtsImpl()
{
m_wsHandler->detachWaitSet(*m_readCondition, this);
delete m_readCondition;
delete m_replier;
}
bool setSubscriberCallback(const SubscriberCallback &subscriberCallback)
{
if (m_subscriberCallback)
{
WARNING_LOG(m_logger) << "Can not set subscriber callback - already set ...";
return false;
}
m_subscriberCallback = subscriberCallback;
return true;
}
bool sendReply(const rti::core::SampleIdentity &requestSampleIdentity, const ReplyTopic &replyData) override final
{
connext::WriteSampleRef<ReplyTopic> reply;
rti::pub::WriteParams replyParams;
reply.set_data(const_cast<ReplyTopic*>(&replyData));
reply.set_info(&replyParams);
m_replier->send_reply(reply, requestSampleIdentity);
return true;
}
bool sendReply(const rti::core::SampleIdentity &requestIdentity, const QVector<ReplyTopic> &replyData) override final
{
DEBUG_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - IN sendReply";
for(int i = 0; i < replyData.size(); ++i)
{
if (HasStatusFunction<ReplyTopic>::value)
{
ReplyTopic rt = replyData.at(i);
setReply(rt, i == replyData.size() - 1 ? Core::FtReplyState::Completed : Core::FtReplyState::InProgress);
if (!sendReply(requestIdentity, rt))
return false;
} else {
if (!sendReply(requestIdentity, replyData.at(i)))
return false;
}
}
return true;
}
protected:
void processRequest(const connext::Sample<RequestTopic> &request)
{
DEBUG_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - processRequest: "
<< connext::DebugInfo::toReadable(request.identity());
qint64 age = qAbs(qint64(request.info().source_timestamp().to_secs()) - time(nullptr));
if (age > 10)
{
std::ostringstream ss;
ss << request.data();
std::string s = ss.str();
int slen = s.length();
static int max_slen = 1024;
if (slen > max_slen)
{
s.resize(max_slen);
s.append("...");
}
DEBUG_LOG(m_logger) << "received a request for topic "
<< TopicNameHelper::requestTopicName()
<< " but it was outdated - ignoring. "
<< " local time: " << (time(nullptr) - 10) << "[s], source timestamp: "
<< qint64(request.info().source_timestamp().to_secs())
<< "[s], -> age: " << age
<< "[s], data: " << s;
ReplyTopic rt;
rt.errorString(tr_lts("dds", "Topic %1 was outdated and therefore ignored. Does the client time match the server time?"));
rt.errorParams({TopicNameHelper::requestTopicName()});
sendReply(request.identity(), rt);
return;
}
sendReplyState(Core::FtReplyState::InProgress, request.identity());
m_subscriberCallback(request.identity(), request.data());
}
void processRequests() override
{
DEBUG_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - processRequests";
while (true)
{
connext::Sample<RequestTopic> request;
{
std::lock_guard<std::mutex> l(m_requestMutex);
if (m_requests.empty())
{
DEBUG_LOG(m_logger) << "No more requests";
return;
}
DEBUG_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - read one request for ";
request = m_requests.front();
m_requests.pop();
}
if (!request.info().valid())
{
WARNING_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - No valid data";
continue;
}
processRequest(request);
}
DEBUG_LOG(m_logger) << TopicNameHelper::requestTopicName() << " - processRequests finished";
}
bool enqueueRequests() override
{
bool bValidDataRead = false;
connext::Sample<RequestTopic> request;
while (m_replier->receive_request(request))
{
if (!request.info().valid())
continue;
bValidDataRead = true;
std::lock_guard<std::mutex> l(m_requestMutex);
m_requests.push(request);
}
return bValidDataRead;
}
private:
connext::Replier<RequestTopic, ReplyTopic> *m_replier;
dds::sub::cond::ReadCondition *m_readCondition;
DDSGeneric::WaitSetHandler *m_wsHandler;
std::queue<connext::Sample<RequestTopic>> m_requests;
std::mutex m_requestMutex;
SubscriberCallback m_subscriberCallback;
NGL::INGLLogger &m_logger;
};
}
+48
View File
@@ -0,0 +1,48 @@
#include "generic_fts_internal.h"
#include <DDS/QosProfile/DDS_DefaultQos.h>
#include <QMetaMethod>
#include <NGLLogger/INGLLogger.h>
#include <qglobal.h>
namespace FTS
{
void GenericFtsInternal::printDefaultQos(NGL::INGLLogger &logger)
{
if (logger.isDebugEnabled())
DDS::QosProfile::print(dds::core::QosProvider::Default(), logger);
}
dds::sub::qos::DataReaderQos GenericFtsInternal::readerQos(NGL::INGLLogger &logger)
{
dds::sub::qos::DataReaderQos qos = DDS::QosProfile::dataReaderDefault(DDS::QosProfile::TopicType::FunctionTopic);
if (logger.isDebugEnabled())
DDS::QosProfile::print(qos, logger);
return qos;
}
dds::pub::qos::DataWriterQos GenericFtsInternal::writerQos(NGL::INGLLogger &logger)
{
dds::pub::qos::DataWriterQos qos = DDS::QosProfile::dataWriterDefault(DDS::QosProfile::TopicType::FunctionTopic);
if (logger.isDebugEnabled())
DDS::QosProfile::print(qos, logger);
return qos;
}
void GenericFtsInternal::dataAvailable()
{
if (!enqueueRequests())
return;
#if QT_VERSION < QT_VERSION_CHECK(5,10,0)
if (!QMetaObject::invokeMethod(this, "processRequests", Qt::QueuedConnection))
abort();
#else
QMetaObject::invokeMethod(this, &GenericFtsInternal::processRequests, Qt::QueuedConnection);
#endif
}
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include "generic_fts.h"
#include <DDS/FTS/ddsfts_export.h>
#include <DDS/Generic/wait_set_handler.h>
#include <dds/sub/qos/DataReaderQos.hpp>
#include <dds/pub/qos/DataWriterQos.hpp>
#include <QObject>
namespace FTS
{
class DDSFTS_EXPORT GenericFtsInternal : public QObject
, protected DDSGeneric::WaitSetHandler::CallbackInterface
{
Q_OBJECT
protected:
GenericFtsInternal() = default;
static void printDefaultQos(NGL::INGLLogger &logger);
static dds::sub::qos::DataReaderQos readerQos(NGL::INGLLogger &logger);
static dds::pub::qos::DataWriterQos writerQos(NGL::INGLLogger &logger);
protected:
void dataAvailable() override;
virtual bool enqueueRequests() = 0;
protected Q_SLOTS:
virtual void processRequests() = 0;
};
}