Refactored TransferListener - all logic moved into non-generic subclass and implemented in *.cpp

This commit is contained in:
Pavel Kirienko 2014-04-09 15:06:27 +04:00
parent a8e0037363
commit 311ae8dca1
3 changed files with 78 additions and 82 deletions

View File

@ -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;
};
/**

View File

@ -90,14 +90,34 @@ class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode<TransferListene
{
const DataTypeDescriptor& data_type_;
const TransferCRC crc_base_; ///< Pre-initialized with data type hash, thus constant
MapBase<TransferBufferManagerKey, TransferReceiver>& 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<TransferBufferManagerKey, TransferReceiver>& 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 <unsigned MaxBufSize, unsigned NumStaticBufs, unsigned NumStaticReceivers>
class UAVCAN_EXPORT TransferListener : public TransferListenerBase
{
typedef TransferBufferManager<MaxBufSize, NumStaticBufs> BufferManager;
BufferManager bufmgr_;
TransferBufferManager<MaxBufSize, NumStaticBufs> bufmgr_;
Map<TransferBufferManagerKey, TransferReceiver, NumStaticReceivers> 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 <unsigned MaxBufSize, unsigned NumStaticBufs, unsigned NumStaticReceivers>
bool TransferListener<MaxBufSize, NumStaticBufs, NumStaticReceivers>::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 <unsigned MaxBufSize, unsigned NumStaticBufs, unsigned NumStaticReceivers>
void TransferListener<MaxBufSize, NumStaticBufs, NumStaticReceivers>::cleanup(MonotonicTime ts)
{
receivers_.removeWhere(TimedOutReceiverPredicate(ts, bufmgr_));
assert(receivers_.isEmpty() ? bufmgr_.isEmpty() : 1);
}
template <unsigned MaxBufSize, unsigned NumStaticBufs, unsigned NumStaticReceivers>
void TransferListener<MaxBufSize, NumStaticBufs, NumStaticReceivers>::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<>
*/

View File

@ -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);
}
}