From 311ae8dca142fb1da340757c0af07172d4138115 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Wed, 9 Apr 2014 15:06:27 +0400 Subject: [PATCH] Refactored TransferListener - all logic moved into non-generic subclass and implemented in *.cpp --- .../uavcan/transport/transfer_buffer.hpp | 1 + .../uavcan/transport/transfer_listener.hpp | 108 +++++------------- .../src/transport/uc_transfer_listener.cpp | 51 +++++++++ 3 files changed, 78 insertions(+), 82 deletions(-) diff --git a/libuavcan/include/uavcan/transport/transfer_buffer.hpp b/libuavcan/include/uavcan/transport/transfer_buffer.hpp index a93929234d..426d849cda 100644 --- a/libuavcan/include/uavcan/transport/transfer_buffer.hpp +++ b/libuavcan/include/uavcan/transport/transfer_buffer.hpp @@ -227,6 +227,7 @@ public: virtual ITransferBuffer* access(const TransferBufferManagerKey& key) = 0; virtual ITransferBuffer* create(const TransferBufferManagerKey& key) = 0; virtual void remove(const TransferBufferManagerKey& key) = 0; + virtual bool isEmpty() const = 0; }; /** diff --git a/libuavcan/include/uavcan/transport/transfer_listener.hpp b/libuavcan/include/uavcan/transport/transfer_listener.hpp index b59094dfc9..b92fcd9931 100644 --- a/libuavcan/include/uavcan/transport/transfer_listener.hpp +++ b/libuavcan/include/uavcan/transport/transfer_listener.hpp @@ -90,14 +90,34 @@ class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode& receivers_; + ITransferBufferManager& bufmgr_; TransferPerfCounter& perf_; + class TimedOutReceiverPredicate + { + const MonotonicTime ts_; + ITransferBufferManager& bufmgr_; + + public: + TimedOutReceiverPredicate(MonotonicTime ts, ITransferBufferManager& bufmgr) + : ts_(ts) + , bufmgr_(bufmgr) + { } + + bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const; + }; + bool checkPayloadCrc(const uint16_t compare_with, const ITransferBuffer& tbb) const; protected: - TransferListenerBase(TransferPerfCounter& perf, const DataTypeDescriptor& data_type) + TransferListenerBase(TransferPerfCounter& perf, const DataTypeDescriptor& data_type, + MapBase& receivers, + ITransferBufferManager& bufmgr) : data_type_(data_type) , crc_base_(data_type.getSignature().toTransferCRC()) + , receivers_(receivers) + , bufmgr_(bufmgr) , perf_(perf) { } @@ -110,8 +130,9 @@ protected: public: const DataTypeDescriptor& getDataTypeDescriptor() const { return data_type_; } - virtual void handleFrame(const RxFrame& frame) = 0; - virtual void cleanup(MonotonicTime ts) = 0; + void cleanup(MonotonicTime ts); + + virtual void handleFrame(const RxFrame& frame); }; /** @@ -120,32 +141,12 @@ public: template class UAVCAN_EXPORT TransferListener : public TransferListenerBase { - typedef TransferBufferManager BufferManager; - BufferManager bufmgr_; + TransferBufferManager bufmgr_; Map receivers_; - class TimedOutReceiverPredicate - { - const MonotonicTime ts_; - BufferManager& bufmgr_; - - public: - TimedOutReceiverPredicate(MonotonicTime ts, BufferManager& bufmgr) - : ts_(ts) - , bufmgr_(bufmgr) - { } - - bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const; - }; - - void cleanup(MonotonicTime ts); - -protected: - void handleFrame(const RxFrame& frame); - public: TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type, IAllocator& allocator) - : TransferListenerBase(perf, data_type) + : TransferListenerBase(perf, data_type, receivers_, bufmgr_) , bufmgr_(allocator) , receivers_(allocator) { @@ -212,63 +213,6 @@ public: // ---------------------------------------------------------------------------- -/* - * TransferListener<>::TimedOutReceiverPredicate - */ -template -bool TransferListener::TimedOutReceiverPredicate::operator() -(const TransferBufferManagerKey& key, const TransferReceiver& value) const -{ - if (value.isTimedOut(ts_)) - { - UAVCAN_TRACE("TransferListener", "Timed out receiver: %s", key.toString().c_str()); - /* - * TransferReceivers do not own their buffers - this helps the Map<> container to copy them - * around quickly and safely (using default assignment operator). Downside is that we need to - * destroy the buffers manually. - * Maybe it is not good that the predicate has side effects, but I ran out of better ideas. - */ - bufmgr_.remove(key); - return true; - } - return false; -} - -/* - * TransferListener<> - */ -template -void TransferListener::cleanup(MonotonicTime ts) -{ - receivers_.removeWhere(TimedOutReceiverPredicate(ts, bufmgr_)); - assert(receivers_.isEmpty() ? bufmgr_.isEmpty() : 1); -} - -template -void TransferListener::handleFrame(const RxFrame& frame) -{ - const TransferBufferManagerKey key(frame.getSrcNodeID(), frame.getTransferType()); - - TransferReceiver* recv = receivers_.access(key); - if (recv == NULL) - { - if (!frame.isFirst()) - { - return; - } - - TransferReceiver new_recv; - recv = receivers_.insert(key, new_recv); - if (recv == NULL) - { - UAVCAN_TRACE("TransferListener", "Receiver registration failed; frame %s", frame.toString().c_str()); - return; - } - } - TransferBufferAccessor tba(bufmgr_, key); - handleReception(*recv, frame, tba); -} - /* * ServiceResponseTransferListener<> */ diff --git a/libuavcan/src/transport/uc_transfer_listener.cpp b/libuavcan/src/transport/uc_transfer_listener.cpp index 69c320666b..808dcd4102 100644 --- a/libuavcan/src/transport/uc_transfer_listener.cpp +++ b/libuavcan/src/transport/uc_transfer_listener.cpp @@ -74,6 +74,27 @@ int MultiFrameIncomingTransfer::read(unsigned offset, uint8_t* data, unsigned le return tbb->read(offset, data, len); } +/* + * TransferListenerBase::TimedOutReceiverPredicate + */ +bool TransferListenerBase::TimedOutReceiverPredicate::operator()(const TransferBufferManagerKey& key, + const TransferReceiver& value) const +{ + if (value.isTimedOut(ts_)) + { + UAVCAN_TRACE("TransferListener", "Timed out receiver: %s", key.toString().c_str()); + /* + * TransferReceivers do not own their buffers - this helps the Map<> container to copy them + * around quickly and safely (using default assignment operator). Downside is that we need to + * destroy the buffers manually. + * Maybe it is not good that the predicate has side effects, but I ran out of better ideas. + */ + bufmgr_.remove(key); + return true; + } + return false; +} + /* * TransferListenerBase */ @@ -151,4 +172,34 @@ void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxF } } +void TransferListenerBase::cleanup(MonotonicTime ts) +{ + receivers_.removeWhere(TimedOutReceiverPredicate(ts, bufmgr_)); + assert(receivers_.isEmpty() ? bufmgr_.isEmpty() : 1); +} + +void TransferListenerBase::handleFrame(const RxFrame& frame) +{ + const TransferBufferManagerKey key(frame.getSrcNodeID(), frame.getTransferType()); + + TransferReceiver* recv = receivers_.access(key); + if (recv == NULL) + { + if (!frame.isFirst()) + { + return; + } + + TransferReceiver new_recv; + recv = receivers_.insert(key, new_recv); + if (recv == NULL) + { + UAVCAN_TRACE("TransferListener", "Receiver registration failed; frame %s", frame.toString().c_str()); + return; + } + } + TransferBufferAccessor tba(bufmgr_, key); + handleReception(*recv, frame, tba); +} + }