TransferListener partially implemented

This commit is contained in:
Pavel Kirienko 2014-02-11 21:55:36 +04:00
parent 0acf1b976b
commit 0bc62a74c9
3 changed files with 89 additions and 31 deletions

View File

@ -74,18 +74,16 @@ public:
*/
class MultiFrameIncomingTransfer : public IncomingTransfer, Noncopyable
{
ITransferBufferManager* const bufmgr_;
const TransferBufferManagerKey bufmgr_key_;
TransferBufferAccessor& buf_acc_;
const uint8_t buffer_offset_; ///< Number of bytes to skip from the beginning of the buffer space
public:
MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset, ITransferBufferManager* bufmgr,
const TransferBufferManagerKey& bufmgr_key);
MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset, TransferBufferAccessor& tba);
int read(unsigned int offset, uint8_t* data, unsigned int len) const;
void release() { bufmgr_->remove(bufmgr_key_); }
void release() { buf_acc_.remove(); }
};
/**
* Transport internal, for dispatcher.
* Internal, refer to transport dispatcher.
*/
class TransferListenerBase : public LinkedListNode<TransferListenerBase>
{
@ -100,7 +98,7 @@ protected:
virtual ~TransferListenerBase() { }
void handleReception(TransferReceiver& receiver, const RxFrame& frame);
void handleReception(TransferReceiver& receiver, const RxFrame& frame, TransferBufferAccessor& tba);
virtual void handleIncomingTransfer(IncomingTransfer& transfer) = 0;
@ -112,36 +110,80 @@ public:
/**
* This class should be derived by transfer receivers (subscribers, servers, callers).
*/
template <unsigned int STATIC_BUF_SIZE, unsigned int NUM_STATIC_BUFS>
template <unsigned int MAX_BUF_SIZE, unsigned int NUM_STATIC_BUFS, unsigned int NUM_STATIC_RECEIVERS>
class TransferListener : protected TransferListenerBase, Noncopyable
{
TransferBufferManager<STATIC_BUF_SIZE, NUM_STATIC_BUFS> bufmgr_;
Map<TransferBufferManagerKey, TransferReceiver, NUM_STATIC_BUFS> receivers_;
typedef TransferBufferManager<MAX_BUF_SIZE, NUM_STATIC_BUFS> BufferManager;
BufferManager bufmgr_;
Map<TransferBufferManagerKey, TransferReceiver, NUM_STATIC_RECEIVERS> receivers_;
void handleFrame(const RxFrame& frame)
{
// TODO
const TransferBufferManagerKey key(frame.source_node_id, frame.transfer_type);
TransferReceiver* recv = receivers_.access(key);
if (recv == NULL)
{
if (frame.frame_index != 0) // We don't want to add registrations mid-transfer, that's pointless
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);
}
struct TimedOutReceiverPredicate
class TimedOutReceiverPredicate
{
const uint64_t ts_monotonic;
TimedOutReceiverPredicate(uint64_t ts_monotonic) : ts_monotonic(ts_monotonic) { }
const uint64_t ts_monotonic_;
BufferManager& bufmgr_;
public:
TimedOutReceiverPredicate(uint64_t ts_monotonic, BufferManager& bufmgr)
: ts_monotonic_(ts_monotonic)
, bufmgr_(bufmgr)
{ }
bool operator()(const TransferBufferManagerKey& key, const TransferReceiver& value) const
{
(void)key;
return value.isTimedOut(ts_monotonic);
if (value.isTimedOut(ts_monotonic_))
{
/*
* TransferReceivers do not own their buffers - this helps the Map<> container to copy them
* around quickly and safely (using default operator==()). Downside is that we need to destroy
* the buffers manually.
* Maybe it is not good that the predicate is being using as mapping functor, but I ran out
* of better ideas.
*/
bufmgr_.remove(key);
return true;
}
return false;
}
};
void cleanup(uint64_t ts_monotonic)
{
receivers_.removeWhere(TimedOutReceiverPredicate(ts_monotonic));
receivers_.removeWhere(TimedOutReceiverPredicate(ts_monotonic, bufmgr_));
#if UAVCAN_DEBUG
if (receivers_.isEmpty())
{
assert(bufmgr_.isEmpty());
}
#endif
}
public:
TransferListener(const DataTypeDescriptor* data_type)
TransferListener(const DataTypeDescriptor* data_type, IAllocator* allocator)
: TransferListenerBase(data_type)
, bufmgr_(allocator)
, receivers_(allocator)
{ }
~TransferListener()

View File

@ -41,26 +41,21 @@ int SingleFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsign
* MultiFrameIncomingTransfer
*/
MultiFrameIncomingTransfer::MultiFrameIncomingTransfer(const RxFrame& last_frame, uint8_t buffer_offset,
ITransferBufferManager* bufmgr,
const TransferBufferManagerKey& bufmgr_key)
TransferBufferAccessor& tba)
: IncomingTransfer(last_frame.ts_monotonic, last_frame.ts_utc, last_frame.transfer_type,
last_frame.transfer_id, last_frame.source_node_id)
, bufmgr_(bufmgr)
, bufmgr_key_(bufmgr_key)
, buf_acc_(tba)
, buffer_offset_(buffer_offset)
{
assert(bufmgr);
assert(!bufmgr_key.isEmpty());
assert(last_frame.last_frame);
}
int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigned int len) const
{
const TransferBufferBase* const tbb = const_cast<ITransferBufferManager*>(bufmgr_)->access(bufmgr_key_);
const TransferBufferBase* const tbb = const_cast<TransferBufferAccessor&>(buf_acc_).access();
if (tbb == NULL)
{
UAVCAN_TRACE("MultiFrameIncomingTransfer", "Read failed: no such buffer %s",
bufmgr_key_.toString().c_str());
UAVCAN_TRACE("MultiFrameIncomingTransfer", "Read failed: no such buffer");
return -1;
}
return tbb->read(offset + buffer_offset_, data, len);
@ -70,10 +65,30 @@ int MultiFrameIncomingTransfer::read(unsigned int offset, uint8_t* data, unsigne
* TransferListenerBase
*/
void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxFrame& frame,
const TransferBufferManagerKey& bufmgr_key)
TransferBufferAccessor& tba)
{
const TransferReceiver::ResultCode result = receiver.addFrame(frame, bufmgr_key);
(void)result;
const TransferReceiver::ResultCode result = receiver.addFrame(frame, tba);
switch (result)
{
case TransferReceiver::RESULT_NOT_COMPLETE:
break;
case TransferReceiver::RESULT_SINGLE_FRAME:
{
SingleFrameIncomingTransfer it(frame);
handleIncomingTransfer(it);
break;
}
case TransferReceiver::RESULT_COMPLETE:
{
// TODO: check CRC
// TODO: select the buffer offset
const int buffer_offset = 123;
MultiFrameIncomingTransfer it(frame, buffer_offset, tba);
handleIncomingTransfer(it);
break;
}
}
}
}

View File

@ -76,8 +76,9 @@ TEST(MultiFrameIncomingTransfer, Basic)
const RxFrame frame = makeFrame();
uavcan::TransferBufferManagerKey bufmgr_key(frame.source_node_id, frame.transfer_type);
uavcan::TransferBufferAccessor tba(&bufmgr, bufmgr_key);
MultiFrameIncomingTransfer it(frame, 3, &bufmgr, bufmgr_key);
MultiFrameIncomingTransfer it(frame, 3, tba);
/*
* Empty read must fail