diff --git a/libuavcan/include/uavcan/node/generic_publisher.hpp b/libuavcan/include/uavcan/node/generic_publisher.hpp index 7dde549c00..7991cc5044 100644 --- a/libuavcan/include/uavcan/node/generic_publisher.hpp +++ b/libuavcan/include/uavcan/node/generic_publisher.hpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -20,15 +19,14 @@ namespace uavcan class GenericPublisherBase : Noncopyable { - const MonotonicDuration max_transfer_interval_; // TODO: memory usage can be reduced + TransferSender sender_; MonotonicDuration tx_timeout_; INode& node_; - LazyConstructor sender_; protected: GenericPublisherBase(INode& node, MonotonicDuration tx_timeout, MonotonicDuration max_transfer_interval) - : max_transfer_interval_(max_transfer_interval) + : sender_(node.getDispatcher(), max_transfer_interval) , tx_timeout_(tx_timeout) , node_(node) { @@ -51,7 +49,8 @@ protected: int genericPublish(const IMarshalBuffer& buffer, TransferType transfer_type, NodeID dst_node_id, TransferID* tid, MonotonicTime blocking_deadline); - TransferSender* getTransferSender(); + TransferSender& getTransferSender() { return sender_; } + const TransferSender& getTransferSender() const { return sender_; } public: static MonotonicDuration getMinTxTimeout() { return MonotonicDuration::fromUSec(200); } @@ -66,7 +65,7 @@ public: */ void allowAnonymousTransfers() { - sender_->allowAnonymousTransfers(); + sender_.allowAnonymousTransfers(); } INode& getNode() const { return node_; } @@ -124,12 +123,6 @@ public: { return genericPublish(message, transfer_type, dst_node_id, &tid, blocking_deadline); } - - TransferSender* getTransferSender() - { - (void)checkInit(); - return GenericPublisherBase::getTransferSender(); - } }; // ---------------------------------------------------------------------------- diff --git a/libuavcan/include/uavcan/node/publisher.hpp b/libuavcan/include/uavcan/node/publisher.hpp index 4b95313d24..2b9222d1b5 100644 --- a/libuavcan/include/uavcan/node/publisher.hpp +++ b/libuavcan/include/uavcan/node/publisher.hpp @@ -81,46 +81,20 @@ public: /** * Returns priority of outgoing transfers. - * TODO: Make const. */ - TransferPriority getPriority() + TransferPriority getPriority() const { - // TODO probably TransferSender must be transformed into regular field? - TransferSender* const ts = getTransferSender(); - if (ts != NULL) - { - return ts->getPriority(); - } - else - { - return TransferPriorityNormal; // This is default - } + return BaseType::getTransferSender().getPriority(); } /** * Allows to change the priority of outgoing transfers. * Note that only High, Normal and Low priorities can be used; Service priority is not available for messages. - * Returns negative error code if priority cannot be set, non-negative on success. + * If the priority value is invalid, an assertion failure will be generated, and the value will not be updated. */ - int setPriority(const TransferPriority prio) + void setPriority(const TransferPriority prio) { - if (prio < NumTransferPriorities && prio != TransferPriorityService) - { - TransferSender* const ts = getTransferSender(); // TODO: Static TransferSender? - if (ts != NULL) - { - ts->setPriority(prio); - return 0; - } - else - { - return -ErrLogic; - } - } - else - { - return -ErrInvalidParam; - } + BaseType::getTransferSender().setPriority(prio); } static MonotonicDuration getDefaultTxTimeout() { return MonotonicDuration::fromMSec(10); } diff --git a/libuavcan/include/uavcan/protocol/global_time_sync_master.hpp b/libuavcan/include/uavcan/protocol/global_time_sync_master.hpp index 4b69451a0a..4cab0c4abf 100644 --- a/libuavcan/include/uavcan/protocol/global_time_sync_master.hpp +++ b/libuavcan/include/uavcan/protocol/global_time_sync_master.hpp @@ -51,16 +51,9 @@ class UAVCAN_EXPORT GlobalTimeSyncMaster : protected LoopbackFrameListenerBase const int res = pub_.init(); if (res >= 0) { - TransferSender* const ts = pub_.getTransferSender(); - UAVCAN_ASSERT(ts != NULL); - ts->setIfaceMask(uint8_t(1 << iface_index_)); - ts->setCanIOFlags(CanIOFlagLoopback); - - const int prio_res = pub_.setPriority(TransferPriorityHigh); // Fixed priority - if (prio_res < 0) - { - return prio_res; - } + pub_.getTransferSender().setIfaceMask(uint8_t(1 << iface_index_)); + pub_.getTransferSender().setCanIOFlags(CanIOFlagLoopback); + pub_.setPriority(TransferPriorityHigh); // Fixed priority } return res; } @@ -84,8 +77,8 @@ class UAVCAN_EXPORT GlobalTimeSyncMaster : protected LoopbackFrameListenerBase int publish(TransferID tid, MonotonicTime current_time) { - UAVCAN_ASSERT(pub_.getTransferSender()->getCanIOFlags() == CanIOFlagLoopback); - UAVCAN_ASSERT(pub_.getTransferSender()->getIfaceMask() == (1 << iface_index_)); + UAVCAN_ASSERT(pub_.getTransferSender().getCanIOFlags() == CanIOFlagLoopback); + UAVCAN_ASSERT(pub_.getTransferSender().getIfaceMask() == (1 << iface_index_)); const MonotonicDuration since_prev_pub = current_time - iface_prev_pub_mono_; iface_prev_pub_mono_ = current_time; diff --git a/libuavcan/include/uavcan/protocol/logger.hpp b/libuavcan/include/uavcan/protocol/logger.hpp index 5856e07355..e6e3358152 100644 --- a/libuavcan/include/uavcan/protocol/logger.hpp +++ b/libuavcan/include/uavcan/protocol/logger.hpp @@ -101,7 +101,8 @@ public: { return res; } - return logmsg_pub_.setPriority(TransferPriorityLow); // Fixed priority + logmsg_pub_.setPriority(TransferPriorityLow); // Fixed priority + return 0; } /** diff --git a/libuavcan/include/uavcan/transport/transfer_sender.hpp b/libuavcan/include/uavcan/transport/transfer_sender.hpp index 26d6e0e628..6c45e524bb 100644 --- a/libuavcan/include/uavcan/transport/transfer_sender.hpp +++ b/libuavcan/include/uavcan/transport/transfer_sender.hpp @@ -20,10 +20,10 @@ namespace uavcan class UAVCAN_EXPORT TransferSender { const MonotonicDuration max_transfer_interval_; - const DataTypeDescriptor& data_type_; + DataTypeID data_type_id_; TransferPriority priority_; - const CanTxQueue::Qos qos_; - const TransferCRC crc_base_; + CanTxQueue::Qos qos_; + TransferCRC crc_base_; CanIOFlags flags_; uint8_t iface_mask_; bool allow_anonymous_transfers_; @@ -43,16 +43,30 @@ public: TransferSender(Dispatcher& dispatcher, const DataTypeDescriptor& data_type, CanTxQueue::Qos qos, MonotonicDuration max_transfer_interval = getDefaultMaxTransferInterval()) : max_transfer_interval_(max_transfer_interval) - , data_type_(data_type) , priority_(TransferPriorityNormal) - , qos_(qos) - , crc_base_(data_type.getSignature().toTransferCRC()) + , qos_(CanTxQueue::Qos()) + , flags_(CanIOFlags(0)) + , iface_mask_(AllIfacesMask) + , allow_anonymous_transfers_(false) + , dispatcher_(dispatcher) + { + init(data_type, qos); + } + + TransferSender(Dispatcher& dispatcher, MonotonicDuration max_transfer_interval = getDefaultMaxTransferInterval()) + : max_transfer_interval_(max_transfer_interval) + , priority_(TransferPriorityNormal) + , qos_(CanTxQueue::Qos()) , flags_(CanIOFlags(0)) , iface_mask_(AllIfacesMask) , allow_anonymous_transfers_(false) , dispatcher_(dispatcher) { } + void init(const DataTypeDescriptor& dtid, CanTxQueue::Qos qos); + + bool isInitialized() const { return data_type_id_ != DataTypeID(); } + CanIOFlags getCanIOFlags() const { return flags_; } void setCanIOFlags(CanIOFlags flags) { flags_ = flags; } diff --git a/libuavcan/src/node/uc_generic_publisher.cpp b/libuavcan/src/node/uc_generic_publisher.cpp index 09f361f5b0..73ab834d96 100644 --- a/libuavcan/src/node/uc_generic_publisher.cpp +++ b/libuavcan/src/node/uc_generic_publisher.cpp @@ -9,7 +9,7 @@ namespace uavcan bool GenericPublisherBase::isInited() const { - return bool(sender_); + return sender_.isInitialized(); } int GenericPublisherBase::doInit(DataTypeKind dtkind, const char* dtname, CanTxQueue::Qos qos) @@ -22,13 +22,14 @@ int GenericPublisherBase::doInit(DataTypeKind dtkind, const char* dtname, CanTxQ GlobalDataTypeRegistry::instance().freeze(); const DataTypeDescriptor* const descr = GlobalDataTypeRegistry::instance().find(dtkind, dtname); - if (!descr) + if (descr == NULL) { UAVCAN_TRACE("GenericPublisher", "Type [%s] is not registered", dtname); return -ErrUnknownDataType; } - sender_.construct - (node_.getDispatcher(), *descr, qos, max_transfer_interval_); + + sender_.init(*descr, qos); + return 0; } @@ -47,21 +48,16 @@ int GenericPublisherBase::genericPublish(const IMarshalBuffer& buffer, TransferT { if (tid) { - return sender_->send(buffer.getDataPtr(), buffer.getMaxWritePos(), getTxDeadline(), - blocking_deadline, transfer_type, dst_node_id, *tid); + return sender_.send(buffer.getDataPtr(), buffer.getMaxWritePos(), getTxDeadline(), + blocking_deadline, transfer_type, dst_node_id, *tid); } else { - return sender_->send(buffer.getDataPtr(), buffer.getMaxWritePos(), getTxDeadline(), - blocking_deadline, transfer_type, dst_node_id); + return sender_.send(buffer.getDataPtr(), buffer.getMaxWritePos(), getTxDeadline(), + blocking_deadline, transfer_type, dst_node_id); } } -TransferSender* GenericPublisherBase::getTransferSender() -{ - return sender_.isConstructed() ? static_cast(sender_) : NULL; -} - void GenericPublisherBase::setTxTimeout(MonotonicDuration tx_timeout) { tx_timeout = max(tx_timeout, getMinTxTimeout()); diff --git a/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp b/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp index f6150ed3ac..173314ed81 100644 --- a/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp +++ b/libuavcan/src/protocol/uc_dynamic_node_id_client.cpp @@ -160,11 +160,7 @@ int DynamicNodeIDClient::start(const protocol::HardwareVersion& hardware_version return res; } dnida_pub_.allowAnonymousTransfers(); - res = dnida_pub_.setPriority(transfer_priority); - if (res < 0) - { - return res; - } + dnida_pub_.setPriority(transfer_priority); res = dnida_sub_.start(AllocationCallback(this, &DynamicNodeIDClient::handleAllocation)); if (res < 0) diff --git a/libuavcan/src/protocol/uc_node_status_provider.cpp b/libuavcan/src/protocol/uc_node_status_provider.cpp index bd090adb10..736050628f 100644 --- a/libuavcan/src/protocol/uc_node_status_provider.cpp +++ b/libuavcan/src/protocol/uc_node_status_provider.cpp @@ -71,11 +71,7 @@ int NodeStatusProvider::startAndPublish(TransferPriority priority) int res = -1; - res = node_status_pub_.setPriority(priority); - if (res < 0) - { - goto fail; - } + node_status_pub_.setPriority(priority); if (!getNode().isPassiveMode()) { diff --git a/libuavcan/src/transport/uc_transfer_sender.cpp b/libuavcan/src/transport/uc_transfer_sender.cpp index 6f49f7a635..232ce82235 100644 --- a/libuavcan/src/transport/uc_transfer_sender.cpp +++ b/libuavcan/src/transport/uc_transfer_sender.cpp @@ -15,6 +15,15 @@ void TransferSender::registerError() const dispatcher_.getTransferPerfCounter().addError(); } +void TransferSender::init(const DataTypeDescriptor& dtid, CanTxQueue::Qos qos) +{ + UAVCAN_ASSERT(!isInitialized()); + + qos_ = qos; + data_type_id_ = dtid.getID(); + crc_base_ = dtid.getSignature().toTransferCRC(); +} + int TransferSender::send(const uint8_t* payload, unsigned payload_len, MonotonicTime tx_deadline, MonotonicTime blocking_deadline, TransferType transfer_type, NodeID dst_node_id, TransferID tid) const @@ -24,7 +33,7 @@ int TransferSender::send(const uint8_t* payload, unsigned payload_len, Monotonic return -ErrTransferTooLong; } - Frame frame(data_type_.getID(), transfer_type, dispatcher_.getNodeID(), dst_node_id, 0, tid); + Frame frame(data_type_id_, transfer_type, dispatcher_.getNodeID(), dst_node_id, 0, tid); if (transfer_type == TransferTypeMessageBroadcast || transfer_type == TransferTypeMessageUnicast) { @@ -143,7 +152,7 @@ int TransferSender::send(const uint8_t* payload, unsigned payload_len, Monotonic /* * TODO: TID is not needed for anonymous transfers, this part of the code can be skipped? */ - const OutgoingTransferRegistryKey otr_key(data_type_.getID(), transfer_type, dst_node_id); + const OutgoingTransferRegistryKey otr_key(data_type_id_, transfer_type, dst_node_id); UAVCAN_ASSERT(!tx_deadline.isZero()); const MonotonicTime otr_deadline = tx_deadline + max_transfer_interval_; @@ -151,8 +160,8 @@ int TransferSender::send(const uint8_t* payload, unsigned payload_len, Monotonic TransferID* const tid = dispatcher_.getOutgoingTransferRegistry().accessOrCreate(otr_key, otr_deadline); if (tid == NULL) { - UAVCAN_TRACE("TransferSender", "OTR access failure, dtd=%s tt=%i", - data_type_.toString().c_str(), int(transfer_type)); + UAVCAN_TRACE("TransferSender", "OTR access failure, dtid=%d tt=%i", + int(data_type_id_.get()), int(transfer_type)); return -ErrMemory; } diff --git a/libuavcan/test/node/publisher.cpp b/libuavcan/test/node/publisher.cpp index 61a57ea1c2..231a25b934 100644 --- a/libuavcan/test/node/publisher.cpp +++ b/libuavcan/test/node/publisher.cpp @@ -18,6 +18,8 @@ TEST(Publisher, Basic) uavcan::Publisher publisher(node); + ASSERT_FALSE(publisher.getTransferSender().isInitialized()); + std::cout << "sizeof(uavcan::Publisher): " << sizeof(uavcan::Publisher) << std::endl; @@ -110,18 +112,5 @@ TEST(Publisher, Basic) * Misc */ ASSERT_TRUE(uavcan::GlobalDataTypeRegistry::instance().isFrozen()); - ASSERT_TRUE(publisher.getTransferSender()); -} - - -TEST(Publisher, ImplicitInitialization) -{ - SystemClockMock clock_mock(100); - CanDriverMock can_driver(2, clock_mock); - TestNode node(can_driver, clock_mock, 1); - - uavcan::Publisher publisher(node); - - // Will be initialized ad-hoc - ASSERT_TRUE(publisher.getTransferSender()); + ASSERT_TRUE(publisher.getTransferSender().isInitialized()); }