#pragma once #include "ddkit/access/TopicPool.hpp" #include "ddkit/access/Topic.hpp" #include "ddkit/access/Writer.hpp" #include "ddkit/utils/system.hpp" namespace ddkit { namespace access { class TopicPoolWrite final { public: TopicPoolWrite( Participant& participant, const IQosStrategyPtr& qosStrategy, const ITopicStrategyPtr& topicStrategy); ~TopicPoolWrite(); // create or get writer template std::shared_ptr> writer() { DDKIT_LOG_TRACE; std::unique_lock lock(m_mutex); createTopicWriteIf(); // must be done here and not in Topic (because TopicPool and qos access needed) std::shared_ptr> topic = m_topicPool.topic(); if(topic) { auto writer = topic->writer(); if(!writer){ ddkit::log::error() << "TopicPoolWrite::writer: no writer in topic"; } return writer; } else { ddkit::log::error() << "TopicPoolWrite::writer: no topic in topic pool"; } return nullptr; } // shortcut, no interface+virtual possible (templates) template void write(T const& t) { bool isOkUnconnected = false; bool isThrowUnconnected = false; writeIntern(t, isOkUnconnected, isThrowUnconnected); } template void writeUnconnectedOk(T const& t) { bool isOkUnconnected = true; bool isThrowUnconnected = false; writeIntern(t, isOkUnconnected, isThrowUnconnected); } template void writeUnconnectedThrow(T const& t) { bool isOkUnconnected = false; bool isThrowUnconnected = false; writeIntern(t, isOkUnconnected, isThrowUnconnected); } private: template void writeIntern(T const& t, bool isOkUnconnected, bool isThrowUnconnected) { ddkit::log::trace() << "writing " << dds::topic::topic_type_name::value() << ":" << t; createTopicWriteIf(); std::unique_lock lock(m_mutex); auto currentWriter = writer(); if(currentWriter){ currentWriter->send(t, isOkUnconnected, isThrowUnconnected); } else { ddkit::log::error() << "TopicPoolWrite::writeIntern: no writer in topic pool"; } } template void createTopicWrite() { std::unique_lock lock(m_mutex); std::string topicName = m_topicPool.getTopicName(); std::shared_ptr> topic = m_topicPool.topic(); std::string typeName = topic->typeName(); if(!topic) { ddkit::log::error() << "TopicPoolWrite::createTopicWrite: no topic in topic pool."; return; } if(topic->hasWriter()) { ddkit::log::error() << "TopicPoolWrite::createTopicWrite: Writer (" << topicName << ") already exists."; return; } QosPattern qosPattern = m_topicPool.qosPattern(typeName); dds::pub::qos::DataWriterQos dataWriterQos = qosPattern.qosWrite(); dds::pub::qos::PublisherQos pubQos = qosPattern.qosPub(); auto writer = std::make_shared>(topic, dataWriterQos, pubQos); topic->setWriter(writer); } template void createTopicWriteIf() { std::unique_lock lock(m_mutex); std::shared_ptr> topic = m_topicPool.topic(); if (topic && !topic->hasWriter()) { createTopicWrite(); } } public: template void dispose(T const& t) { std::unique_lock lock(m_mutex); auto currentWriter = writer(); if(currentWriter){ currentWriter->dispose(t); } else { ddkit::log::error() << "TopicPoolWrite::dispose: no writer in topic pool"; } } void closeWriters(); private: std::recursive_mutex m_mutex; TopicPool m_topicPool; TopicPoolWrite(TopicPoolWrite const&) = delete; void operator=(TopicPoolWrite const&) = delete; }; } // namespace access } // namespace ddkit