117 lines
4.4 KiB
C++
117 lines
4.4 KiB
C++
#pragma once
|
|
|
|
#include "ddkit/access/DdsWrap.hpp"
|
|
#include "ddkit/access/Topic.hpp"
|
|
#include "ddkit/access/Listener.hpp"
|
|
#include "ddkit/access/ConnectState.hpp"
|
|
|
|
#include "ddkit/utils/Logger.hpp"
|
|
|
|
namespace ddkit {
|
|
namespace access {
|
|
|
|
template <typename T>
|
|
class Writer final {
|
|
|
|
public:
|
|
explicit Writer(std::shared_ptr<Topic<T>> topic, dds::pub::qos::DataWriterQos dataWriterQos, dds::pub::qos::PublisherQos pubQos)
|
|
: m_connectState(std::make_shared<ConnectState>(topic->topicName(), topic->topicNameModule(), topic->topicNameTopic()))
|
|
, m_listener(std::make_shared<ListenerWrite<T> >(m_connectState))
|
|
, m_writer(dataWriter(topic, m_listener.get(), dataWriterQos, pubQos)) {
|
|
DDKIT_LOG_TRACE;
|
|
}
|
|
|
|
~Writer() {
|
|
DDKIT_LOG_TRACE;
|
|
// ddkit::log::info() << "closing writer!";
|
|
m_writer.close();
|
|
}
|
|
|
|
bool isConnected() { return m_connectState->isConnected(); }
|
|
void waitUntilConnected() { m_connectState->waitUntilConnected(); }
|
|
|
|
IConnectCheckPtr getConnectCheck() { return m_connectState; }
|
|
|
|
/// @brief isOkUnconnected == true -> do not warn about write while not connected
|
|
/// - one could set this on a late-join-topic to avoid the warnings
|
|
/// isThrowUnconnected == true -> do throw momentarily
|
|
/// - one could set this on a 'checked' write ('Cmd')
|
|
void send(T const& sample, bool isOkUnconnected, bool isThrowUnconnected) {
|
|
ddkit::log::debug() << "send: " << DDKIT_LOG_VAR_VALUE(sample);
|
|
|
|
bool isConnected = m_connectState->isConnected();
|
|
|
|
// return immediately, if Service for command is not yet connected (and told to throw)
|
|
if (!isConnected && isThrowUnconnected) {
|
|
throw std::runtime_error("Service for Cmd is unavailable yet - try later.");
|
|
}
|
|
// todo: as monitor-sessions are not distinguished so far, this (direct) exception will not be thrown,
|
|
// if a monitor is running and connected
|
|
|
|
// warn about probably lost samples (if not told otherwise)
|
|
if (!isConnected && !isOkUnconnected) {
|
|
ddkit::log::info() << "Writer not connected while sending (" << dds::topic::topic_type_name<T>::value() << ").";
|
|
}
|
|
|
|
// do the write
|
|
m_writer.write(sample);
|
|
}
|
|
|
|
void dispose(T const& sample) {
|
|
DDKIT_LOG_TRACE;
|
|
ddkit::log::debug() << "dispose: " << DDKIT_LOG_VAR_VALUE(sample);
|
|
|
|
// Get handle of instance
|
|
auto handle = m_writer.lookup_instance(sample);
|
|
|
|
// Instance has to be known
|
|
if (handle.is_nil()) {
|
|
ddkit::log::error() << "Tried to remove object \"" << sample << "\", which does not exist in dds.";
|
|
return;
|
|
}
|
|
|
|
// We have to do both `dispose_instance` and `unregister_instance`
|
|
// to fully free the instance. If we would just dispose the instance
|
|
// the instance would remain stored by the reader and writer since it
|
|
// remains `active`. Only after the `unregister_instance` the instance
|
|
// has no associated writer and can be freed.
|
|
m_writer.dispose_instance(handle);
|
|
m_writer.unregister_instance(handle);
|
|
}
|
|
|
|
private:
|
|
ConnectStatePtr m_connectState;
|
|
std::shared_ptr<ListenerWrite<T>> m_listener;
|
|
dds::pub::DataWriter<T> m_writer;
|
|
|
|
/// Note on writer-listeners:
|
|
/// - listeners have to be set in the constructor of the writer, because
|
|
/// an event could be missing, when the listener is set afterwards
|
|
/// - all depending on how fast discovery etc is, see also here:
|
|
/// https://github.com/eclipse-cyclonedds/cyclonedds-cxx/issues/378#issuecomment-1463626212
|
|
static dds::pub::DataWriter<T> dataWriter(
|
|
std::shared_ptr<Topic<T>> topic,
|
|
ListenerWrite<T>* listener,
|
|
dds::pub::qos::DataWriterQos dataWriterQos,
|
|
dds::pub::qos::PublisherQos pubQos) {
|
|
|
|
DDKIT_LOG_TRACE;
|
|
|
|
dds::pub::DataWriter<T> ddsWriter = dds::pub::DataWriter<T>(
|
|
dds::pub::Publisher(topic->domainParticipant(), pubQos),
|
|
topic->ddsTopic(),
|
|
dataWriterQos,
|
|
listener,
|
|
dds::core::status::StatusMask::all());
|
|
|
|
return ddsWriter;
|
|
}
|
|
|
|
// no copying
|
|
Writer(Writer const&) = delete;
|
|
Writer(Writer&&) = delete;
|
|
void operator=(Writer const&) = delete;
|
|
};
|
|
|
|
} // namespace access
|
|
} // namespace ddkit
|