Transfer buffering system detemplatized; compiles but tests are failing

This commit is contained in:
Pavel Kirienko 2015-10-14 19:58:51 +03:00
parent 763e96b6ed
commit a9fdf44fa9
20 changed files with 335 additions and 510 deletions

View File

@ -100,9 +100,9 @@ protected:
~GenericSubscriberBase() { }
int genericStart(TransferListenerBase* listener, bool (Dispatcher::*registration_method)(TransferListenerBase*));
int genericStart(TransferListener* listener, bool (Dispatcher::*registration_method)(TransferListener*));
void stop(TransferListenerBase* listener);
void stop(TransferListener* listener);
public:
/**
@ -115,22 +115,6 @@ public:
INode& getNode() const { return node_; }
};
/**
* This helper class does some compile-time magic on the transport layer machinery. For authorized personnel only.
*/
template <typename DataStruct_,
template<unsigned> class TransferListenerTemplate = TransferListener
>
class UAVCAN_EXPORT TransferListenerInstantiationHelper
{
enum { DataTypeMaxByteLen = BitLenToByteLen<DataStruct_::MaxBitLen>::Result };
enum { NeedsBuffer = int(DataTypeMaxByteLen) > int(GuaranteedPayloadLenPerFrame) };
enum { BufferSize = NeedsBuffer ? DataTypeMaxByteLen : 0 };
public:
typedef TransferListenerTemplate<BufferSize> Type;
};
/**
* Please note that the reference passed to the RX callback points to a stack-allocated object, which means
* that it gets invalidated shortly after the callback returns.
@ -151,9 +135,15 @@ class UAVCAN_EXPORT GenericSubscriber : public GenericSubscriberBase
}
public:
TransferForwarder(SelfType& obj, const DataTypeDescriptor& data_type, IPoolAllocator& allocator)
: TransferListenerType(obj.node_.getDispatcher().getTransferPerfCounter(), data_type, allocator)
, obj_(obj)
TransferForwarder(SelfType& obj,
const DataTypeDescriptor& data_type,
uint16_t max_buffer_size,
IPoolAllocator& allocator) :
TransferListenerType(obj.node_.getDispatcher().getTransferPerfCounter(),
data_type,
max_buffer_size,
allocator),
obj_(obj)
{ }
};
@ -163,20 +153,19 @@ class UAVCAN_EXPORT GenericSubscriber : public GenericSubscriberBase
void handleIncomingTransfer(IncomingTransfer& transfer);
int genericStart(bool (Dispatcher::*registration_method)(TransferListenerBase*));
int genericStart(bool (Dispatcher::*registration_method)(TransferListener*));
protected:
struct ReceivedDataStructureSpec : public ReceivedDataStructure<DataStruct>
{
ReceivedDataStructureSpec() { }
ReceivedDataStructureSpec(const IncomingTransfer* arg_transfer)
: ReceivedDataStructure<DataStruct>(arg_transfer)
ReceivedDataStructureSpec(const IncomingTransfer* arg_transfer) :
ReceivedDataStructure<DataStruct>(arg_transfer)
{ }
};
explicit GenericSubscriber(INode& node)
: GenericSubscriberBase(node)
explicit GenericSubscriber(INode& node) : GenericSubscriberBase(node)
{ }
virtual ~GenericSubscriber() { stop(); }
@ -247,8 +236,10 @@ int GenericSubscriber<DataSpec, DataStruct, TransferListenerType>::checkInit()
return -ErrUnknownDataType;
}
forwarder_.template construct<SelfType&, const DataTypeDescriptor&, IPoolAllocator&>
(*this, *descr, node_.getAllocator());
static const uint16_t MaxBufferSize = BitLenToByteLen<DataStruct::MaxBitLen>::Result;
forwarder_.template construct<SelfType&, const DataTypeDescriptor&, uint16_t, IPoolAllocator&>
(*this, *descr, MaxBufferSize, node_.getAllocator());
return 0;
}
@ -286,7 +277,7 @@ void GenericSubscriber<DataSpec, DataStruct, TransferListenerType>::handleIncomi
template <typename DataSpec, typename DataStruct, typename TransferListenerType>
int GenericSubscriber<DataSpec, DataStruct, TransferListenerType>::
genericStart(bool (Dispatcher::*registration_method)(TransferListenerBase*))
genericStart(bool (Dispatcher::*registration_method)(TransferListener*))
{
const int res = checkInit();
if (res < 0)

View File

@ -20,15 +20,6 @@
namespace uavcan
{
template <typename ServiceDataType>
class UAVCAN_EXPORT ServiceResponseTransferListenerInstantiationHelper
{
public:
typedef typename TransferListenerInstantiationHelper<typename ServiceDataType::Response,
TransferListenerWithFilter>::Type Type;
};
/**
* This struct describes a pending service call.
* Refer to @ref ServiceClient to learn more about service calls.
@ -225,8 +216,7 @@ template <typename DataType_,
>
class UAVCAN_EXPORT ServiceClient
: public GenericSubscriber<DataType_,
typename DataType_::Response,
typename ServiceResponseTransferListenerInstantiationHelper<DataType_>::Type>
typename DataType_::Response, TransferListenerWithFilter>
, public ServiceClientBase
{
public:
@ -239,8 +229,7 @@ public:
private:
typedef ServiceClient<DataType, Callback> SelfType;
typedef GenericPublisher<DataType, RequestType> PublisherType;
typedef typename ServiceResponseTransferListenerInstantiationHelper<DataType>::Type TransferListenerType;
typedef GenericSubscriber<DataType, ResponseType, TransferListenerType> SubscriberType;
typedef GenericSubscriber<DataType, ResponseType, TransferListenerWithFilter> SubscriberType;
typedef Multiset<CallState> CallRegistry;
@ -537,7 +526,7 @@ int ServiceClient<DataType_, Callback_>::call(NodeID server_node_id, const Reque
* Configuring the listener so it will accept only the matching responses
* TODO move to init(), but this requires to somewhat refactor GenericSubscriber<> (remove TransferForwarder)
*/
TransferListenerType* const tl = SubscriberType::getTransferListener();
TransferListenerWithFilter* const tl = SubscriberType::getTransferListener();
if (tl == NULL)
{
UAVCAN_ASSERT(0); // Must have been created

View File

@ -88,8 +88,7 @@ template <typename DataType_,
#endif
>
class UAVCAN_EXPORT ServiceServer
: public GenericSubscriber<DataType_, typename DataType_::Request,
typename TransferListenerInstantiationHelper<typename DataType_::Request>::Type>
: public GenericSubscriber<DataType_, typename DataType_::Request, TransferListener>
{
public:
typedef DataType_ DataType;
@ -98,8 +97,7 @@ public:
typedef Callback_ Callback;
private:
typedef typename TransferListenerInstantiationHelper<RequestType>::Type TransferListenerType;
typedef GenericSubscriber<DataType, RequestType, TransferListenerType> SubscriberType;
typedef GenericSubscriber<DataType, RequestType, TransferListener> SubscriberType;
typedef GenericPublisher<DataType, ResponseType> PublisherType;
PublisherType publisher_;

View File

@ -43,15 +43,13 @@ template <typename DataType_,
#endif
>
class UAVCAN_EXPORT Subscriber
: public GenericSubscriber<DataType_, DataType_,
typename TransferListenerInstantiationHelper<DataType_>::Type>
: public GenericSubscriber<DataType_, DataType_, TransferListener>
{
public:
typedef Callback_ Callback;
private:
typedef typename TransferListenerInstantiationHelper<DataType_>::Type TransferListenerType;
typedef GenericSubscriber<DataType_, DataType_, TransferListenerType> BaseType;
typedef GenericSubscriber<DataType_, DataType_, TransferListener> BaseType;
Callback callback_;

View File

@ -86,14 +86,14 @@ class UAVCAN_EXPORT Dispatcher : Noncopyable
class ListenerRegistry
{
LinkedListRoot<TransferListenerBase> list_;
LinkedListRoot<TransferListener> list_;
class DataTypeIDInsertionComparator
{
const DataTypeID id_;
public:
explicit DataTypeIDInsertionComparator(DataTypeID id) : id_(id) { }
bool operator()(const TransferListenerBase* listener) const
bool operator()(const TransferListener* listener) const
{
UAVCAN_ASSERT(listener);
return id_ > listener->getDataTypeDescriptor().getID();
@ -103,15 +103,15 @@ class UAVCAN_EXPORT Dispatcher : Noncopyable
public:
enum Mode { UniqueListener, ManyListeners };
bool add(TransferListenerBase* listener, Mode mode);
void remove(TransferListenerBase* listener);
bool add(TransferListener* listener, Mode mode);
void remove(TransferListener* listener);
bool exists(DataTypeID dtid) const;
void cleanup(MonotonicTime ts);
void handleFrame(const RxFrame& frame);
unsigned getNumEntries() const { return list_.getLength(); }
const LinkedListRoot<TransferListenerBase>& getList() const { return list_; }
const LinkedListRoot<TransferListener>& getList() const { return list_; }
};
ListenerRegistry lmsg_;
@ -162,13 +162,13 @@ public:
void cleanup(MonotonicTime ts);
bool registerMessageListener(TransferListenerBase* listener);
bool registerServiceRequestListener(TransferListenerBase* listener);
bool registerServiceResponseListener(TransferListenerBase* listener);
bool registerMessageListener(TransferListener* listener);
bool registerServiceRequestListener(TransferListener* listener);
bool registerServiceResponseListener(TransferListener* listener);
void unregisterMessageListener(TransferListenerBase* listener);
void unregisterServiceRequestListener(TransferListenerBase* listener);
void unregisterServiceResponseListener(TransferListenerBase* listener);
void unregisterMessageListener(TransferListener* listener);
void unregisterServiceRequestListener(TransferListener* listener);
void unregisterServiceResponseListener(TransferListener* listener);
bool hasSubscriber(DataTypeID dtid) const;
bool hasPublisher(DataTypeID dtid) const;
@ -185,15 +185,15 @@ public:
* removed from this list as soon as the corresponding service call is complete.
* @{
*/
const LinkedListRoot<TransferListenerBase>& getListOfMessageListeners() const
const LinkedListRoot<TransferListener>& getListOfMessageListeners() const
{
return lmsg_.getList();
}
const LinkedListRoot<TransferListenerBase>& getListOfServiceRequestListeners() const
const LinkedListRoot<TransferListener>& getListOfServiceRequestListeners() const
{
return lsrv_req_.getList();
}
const LinkedListRoot<TransferListenerBase>& getListOfServiceResponseListeners() const
const LinkedListRoot<TransferListener>& getListOfServiceResponseListeners() const
{
return lsrv_resp_.getList();
}

View File

@ -16,6 +16,47 @@
namespace uavcan
{
/**
* Standalone static buffer
*/
class StaticTransferBufferImpl : public ITransferBuffer
{
uint8_t* const data_;
const uint16_t size_;
uint16_t max_write_pos_;
public:
StaticTransferBufferImpl(uint8_t* buf, uint16_t buf_size) :
data_(buf),
size_(buf_size),
max_write_pos_(0)
{ }
virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
virtual int write(unsigned offset, const uint8_t* data, unsigned len);
void reset();
uint16_t getSize() const { return size_; }
uint8_t* getRawPtr() { return data_; }
const uint8_t* getRawPtr() const { return data_; }
uint16_t getMaxWritePos() const { return max_write_pos_; }
void setMaxWritePos(uint16_t value) { max_write_pos_ = value; }
};
template <uint16_t Size>
class UAVCAN_EXPORT StaticTransferBuffer : public StaticTransferBufferImpl
{
uint8_t buffer_[Size];
public:
StaticTransferBuffer() : StaticTransferBufferImpl(buffer_, Size)
{
StaticAssert<(Size > 0)>::check();
}
};
/**
* Internal for TransferBufferManager
*/
@ -53,41 +94,13 @@ public:
#endif
};
/**
* Internal for TransferBufferManager
*/
class UAVCAN_EXPORT TransferBufferManagerEntry : public ITransferBuffer, Noncopyable
{
TransferBufferManagerKey key_;
protected:
virtual void resetImpl() = 0;
public:
TransferBufferManagerEntry() { }
explicit TransferBufferManagerEntry(const TransferBufferManagerKey& key)
: key_(key)
{ }
const TransferBufferManagerKey& getKey() const { return key_; }
bool isEmpty() const { return key_.isEmpty(); }
void reset(const TransferBufferManagerKey& key = TransferBufferManagerKey())
{
key_ = key;
resetImpl();
}
};
/**
* Resizable gather/scatter storage.
* reset() call releases all memory blocks.
* Supports unordered write operations - from higher to lower offsets
*/
class UAVCAN_EXPORT DynamicTransferBufferManagerEntry
: public TransferBufferManagerEntry
, public LinkedListNode<DynamicTransferBufferManagerEntry>
class UAVCAN_EXPORT TransferBufferManagerEntry : public ITransferBuffer
, public LinkedListNode<TransferBufferManagerEntry>
{
struct Block : LinkedListNode<Block>
{
@ -107,116 +120,58 @@ class UAVCAN_EXPORT DynamicTransferBufferManagerEntry
LinkedListRoot<Block> blocks_; // Blocks are ordered from lower to higher buffer offset
uint16_t max_write_pos_;
const uint16_t max_size_;
/// Reset functionality must be implemented in a non-virtual method to call it safely from the destructor.
void doReset();
virtual void resetImpl();
TransferBufferManagerKey key_;
public:
DynamicTransferBufferManagerEntry(IPoolAllocator& allocator, uint16_t max_size)
: allocator_(allocator)
, max_write_pos_(0)
, max_size_(max_size)
TransferBufferManagerEntry(IPoolAllocator& allocator, uint16_t max_size) :
allocator_(allocator),
max_write_pos_(0),
max_size_(max_size)
{
StaticAssert<(Block::Size > 8)>::check();
IsDynamicallyAllocatable<Block>::check();
IsDynamicallyAllocatable<DynamicTransferBufferManagerEntry>::check();
IsDynamicallyAllocatable<TransferBufferManagerEntry>::check();
}
virtual ~DynamicTransferBufferManagerEntry()
{
doReset();
}
virtual ~TransferBufferManagerEntry() { reset(); }
static DynamicTransferBufferManagerEntry* instantiate(IPoolAllocator& allocator, uint16_t max_size);
static void destroy(DynamicTransferBufferManagerEntry*& obj, IPoolAllocator& allocator);
virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
virtual int write(unsigned offset, const uint8_t* data, unsigned len);
};
/**
* Standalone static buffer
*/
class StaticTransferBufferImpl : public ITransferBuffer
{
uint8_t* const data_;
const uint16_t size_;
uint16_t max_write_pos_;
public:
StaticTransferBufferImpl(uint8_t* buf, uint16_t buf_size)
: data_(buf)
, size_(buf_size)
, max_write_pos_(0)
{ }
static TransferBufferManagerEntry* instantiate(IPoolAllocator& allocator, uint16_t max_size);
static void destroy(TransferBufferManagerEntry*& obj, IPoolAllocator& allocator);
virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
virtual int write(unsigned offset, const uint8_t* data, unsigned len);
void reset();
void reset(const TransferBufferManagerKey& key = TransferBufferManagerKey());
uint16_t getSize() const { return size_; }
uint8_t* getRawPtr() { return data_; }
const uint8_t* getRawPtr() const { return data_; }
uint16_t getMaxWritePos() const { return max_write_pos_; }
void setMaxWritePos(uint16_t value) { max_write_pos_ = value; }
};
template <uint16_t Size>
class UAVCAN_EXPORT StaticTransferBuffer : public StaticTransferBufferImpl
{
uint8_t buffer_[Size];
public:
StaticTransferBuffer()
: StaticTransferBufferImpl(buffer_, Size)
{
StaticAssert<(Size > 0)>::check();
}
const TransferBufferManagerKey& getKey() const { return key_; }
bool isEmpty() const { return key_.isEmpty(); }
};
/**
* Statically allocated storage for the buffer manager
* Buffer manager implementation.
*/
class StaticTransferBufferManagerEntryImpl : public TransferBufferManagerEntry
class TransferBufferManager : public Noncopyable
{
StaticTransferBufferImpl buf_;
LinkedListRoot<TransferBufferManagerEntry> buffers_;
IPoolAllocator& allocator_;
const uint16_t max_buf_size_;
virtual void resetImpl();
TransferBufferManagerEntry* findFirst(const TransferBufferManagerKey& key);
public:
StaticTransferBufferManagerEntryImpl(uint8_t* buf, uint16_t buf_size)
: buf_(buf, buf_size)
TransferBufferManager(uint16_t max_buf_size, IPoolAllocator& allocator) :
allocator_(allocator),
max_buf_size_(max_buf_size)
{ }
virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
virtual int write(unsigned offset, const uint8_t* data, unsigned len);
};
~TransferBufferManager();
template <uint16_t Size>
class UAVCAN_EXPORT StaticTransferBufferManagerEntry : public StaticTransferBufferManagerEntryImpl
{
uint8_t buffer_[Size];
public:
StaticTransferBufferManagerEntry()
: StaticTransferBufferManagerEntryImpl(buffer_, Size)
{ }
};
ITransferBuffer* access(const TransferBufferManagerKey& key);
ITransferBuffer* create(const TransferBufferManagerKey& key);
void remove(const TransferBufferManagerKey& key);
bool isEmpty() const;
/**
* Manages different storage types (static/dynamic) for transfer reception logic.
*/
class UAVCAN_EXPORT ITransferBufferManager
{
public:
virtual ~ITransferBufferManager() { }
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;
unsigned getNumBuffers() const;
};
/**
@ -224,13 +179,13 @@ public:
*/
class UAVCAN_EXPORT TransferBufferAccessor
{
ITransferBufferManager& bufmgr_;
TransferBufferManager& bufmgr_;
const TransferBufferManagerKey key_;
public:
TransferBufferAccessor(ITransferBufferManager& bufmgr, TransferBufferManagerKey key)
: bufmgr_(bufmgr)
, key_(key)
TransferBufferAccessor(TransferBufferManager& bufmgr, TransferBufferManagerKey key) :
bufmgr_(bufmgr),
key_(key)
{
UAVCAN_ASSERT(!key.isEmpty());
}
@ -239,54 +194,6 @@ public:
void remove() { bufmgr_.remove(key_); }
};
/**
* Buffer manager implementation.
*/
class TransferBufferManagerImpl : public ITransferBufferManager, Noncopyable
{
LinkedListRoot<DynamicTransferBufferManagerEntry> dynamic_buffers_;
IPoolAllocator& allocator_;
const uint16_t max_buf_size_;
DynamicTransferBufferManagerEntry* findFirstDynamic(const TransferBufferManagerKey& key);
public:
TransferBufferManagerImpl(uint16_t max_buf_size, IPoolAllocator& allocator)
: allocator_(allocator)
, max_buf_size_(max_buf_size)
{ }
virtual ~TransferBufferManagerImpl();
virtual ITransferBuffer* access(const TransferBufferManagerKey& key);
virtual ITransferBuffer* create(const TransferBufferManagerKey& key);
virtual void remove(const TransferBufferManagerKey& key);
virtual bool isEmpty() const;
unsigned getNumBuffers() const;
};
template <uint16_t MaxBufSize>
class UAVCAN_EXPORT TransferBufferManager : public TransferBufferManagerImpl
{
public:
explicit TransferBufferManager(IPoolAllocator& allocator) :
TransferBufferManagerImpl(MaxBufSize, allocator)
{ }
};
template <>
class UAVCAN_EXPORT TransferBufferManager<0> : public ITransferBufferManager
{
public:
TransferBufferManager() { }
TransferBufferManager(IPoolAllocator&) { }
virtual ITransferBuffer* access(const TransferBufferManagerKey&) { return NULL; }
virtual ITransferBuffer* create(const TransferBufferManagerKey&) { return NULL; }
virtual void remove(const TransferBufferManagerKey&) { }
virtual bool isEmpty() const { return true; }
};
}
#endif // UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED

View File

@ -96,11 +96,11 @@ public:
/**
* Internal, refer to the transport dispatcher class.
*/
class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode<TransferListenerBase>, Noncopyable
class UAVCAN_EXPORT TransferListener : public LinkedListNode<TransferListener>, Noncopyable
{
const DataTypeDescriptor& data_type_;
Map<TransferBufferManagerKey, TransferReceiver>& receivers_;
ITransferBufferManager& bufmgr_;
TransferBufferManager bufmgr_;
Map<TransferBufferManagerKey, TransferReceiver> receivers_;
TransferPerfCounter& perf_;
const TransferCRC crc_base_; ///< Pre-initialized with data type hash, thus constant
bool allow_anonymous_transfers_;
@ -108,10 +108,10 @@ class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode<TransferListene
class TimedOutReceiverPredicate
{
const MonotonicTime ts_;
ITransferBufferManager& parent_bufmgr_;
TransferBufferManager& parent_bufmgr_;
public:
TimedOutReceiverPredicate(MonotonicTime arg_ts, ITransferBufferManager& arg_bufmgr)
TimedOutReceiverPredicate(MonotonicTime arg_ts, TransferBufferManager& arg_bufmgr)
: ts_(arg_ts)
, parent_bufmgr_(arg_bufmgr)
{ }
@ -122,25 +122,28 @@ class UAVCAN_EXPORT TransferListenerBase : public LinkedListNode<TransferListene
bool checkPayloadCrc(const uint16_t compare_with, const ITransferBuffer& tbb) const;
protected:
TransferListenerBase(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
Map<TransferBufferManagerKey, TransferReceiver>& receivers,
ITransferBufferManager& bufmgr)
: data_type_(data_type)
, receivers_(receivers)
, bufmgr_(bufmgr)
, perf_(perf)
, crc_base_(data_type.getSignature().toTransferCRC())
, allow_anonymous_transfers_(false)
{ }
virtual ~TransferListenerBase() { }
void handleReception(TransferReceiver& receiver, const RxFrame& frame, TransferBufferAccessor& tba);
void handleAnonymousTransferReception(const RxFrame& frame);
virtual void handleIncomingTransfer(IncomingTransfer& transfer) = 0;
public:
TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
uint16_t max_buffer_size, IPoolAllocator& allocator)
: data_type_(data_type)
, bufmgr_(max_buffer_size, allocator)
, receivers_(allocator)
, perf_(perf)
, crc_base_(data_type.getSignature().toTransferCRC())
, allow_anonymous_transfers_(false)
{ }
virtual ~TransferListener()
{
// Map must be cleared before bufmgr is destroyed
receivers_.clear();
}
const DataTypeDescriptor& getDataTypeDescriptor() const { return data_type_; }
/**
@ -154,29 +157,6 @@ public:
virtual void handleFrame(const RxFrame& frame);
};
/**
* This class should be derived by transfer receivers (subscribers, servers).
*/
template <unsigned MaxBufSize>
class UAVCAN_EXPORT TransferListener : public TransferListenerBase
{
TransferBufferManager<MaxBufSize> bufmgr_;
Map<TransferBufferManagerKey, TransferReceiver> receivers_;
public:
TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type, IPoolAllocator& allocator)
: TransferListenerBase(perf, data_type, receivers_, bufmgr_)
, bufmgr_(allocator)
, receivers_(allocator)
{ }
virtual ~TransferListener()
{
// Map must be cleared before bufmgr is destroyed
receivers_.clear();
}
};
/**
* This class is used by transfer listener to decide if the frame should be accepted or ignored.
*/
@ -194,19 +174,16 @@ public:
/**
* This class should be derived by callers.
*/
template <unsigned MaxBufSize>
class UAVCAN_EXPORT TransferListenerWithFilter : public TransferListener<MaxBufSize>
class UAVCAN_EXPORT TransferListenerWithFilter : public TransferListener
{
const ITransferAcceptanceFilter* filter_;
virtual void handleFrame(const RxFrame& frame);
public:
typedef TransferListener<MaxBufSize> BaseType;
TransferListenerWithFilter(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
IPoolAllocator& allocator)
: BaseType(perf, data_type, allocator)
uint16_t max_buffer_size, IPoolAllocator& allocator)
: TransferListener(perf, data_type, max_buffer_size, allocator)
, filter_(NULL)
{ }
@ -216,27 +193,6 @@ public:
}
};
// ----------------------------------------------------------------------------
/*
* TransferListenerWithFilter<>
*/
template <unsigned MaxBufSize>
void TransferListenerWithFilter<MaxBufSize>::handleFrame(const RxFrame& frame)
{
if (filter_ != NULL)
{
if (filter_->shouldAcceptFrame(frame))
{
BaseType::handleFrame(frame);
}
}
else
{
UAVCAN_ASSERT(0);
}
}
}
#endif // UAVCAN_TRANSPORT_TRANSFER_LISTENER_HPP_INCLUDED

View File

@ -7,8 +7,8 @@
namespace uavcan
{
int GenericSubscriberBase::genericStart(TransferListenerBase* listener,
bool (Dispatcher::*registration_method)(TransferListenerBase*))
int GenericSubscriberBase::genericStart(TransferListener* listener,
bool (Dispatcher::*registration_method)(TransferListener*))
{
if (listener == NULL)
{
@ -24,7 +24,7 @@ int GenericSubscriberBase::genericStart(TransferListenerBase* listener,
return 0;
}
void GenericSubscriberBase::stop(TransferListenerBase* listener)
void GenericSubscriberBase::stop(TransferListener* listener)
{
if (listener != NULL)
{

View File

@ -38,8 +38,8 @@ int16_t CanAcceptanceFilterConfigurator::loadInputConfiguration(AnonymousMessage
return -ErrMemory;
}
const TransferListenerBase* p = node_.getDispatcher().getListOfMessageListeners().get();
while (p)
const TransferListener* p = node_.getDispatcher().getListOfMessageListeners().get();
while (p != NULL)
{
CanFilterConfig cfg;
cfg.id = static_cast<uint32_t>(p->getDataTypeDescriptor().getID().get()) << 8;

View File

@ -72,11 +72,11 @@ void LoopbackFrameListenerRegistry::invokeListeners(RxFrame& frame)
/*
* Dispatcher::ListenerRegister
*/
bool Dispatcher::ListenerRegistry::add(TransferListenerBase* listener, Mode mode)
bool Dispatcher::ListenerRegistry::add(TransferListener* listener, Mode mode)
{
if (mode == UniqueListener)
{
TransferListenerBase* p = list_.get();
TransferListener* p = list_.get();
while (p)
{
if (p->getDataTypeDescriptor().getID() == listener->getDataTypeDescriptor().getID())
@ -91,14 +91,14 @@ bool Dispatcher::ListenerRegistry::add(TransferListenerBase* listener, Mode mode
return true;
}
void Dispatcher::ListenerRegistry::remove(TransferListenerBase* listener)
void Dispatcher::ListenerRegistry::remove(TransferListener* listener)
{
list_.remove(listener);
}
bool Dispatcher::ListenerRegistry::exists(DataTypeID dtid) const
{
TransferListenerBase* p = list_.get();
TransferListener* p = list_.get();
while (p)
{
if (p->getDataTypeDescriptor().getID() == dtid)
@ -112,10 +112,10 @@ bool Dispatcher::ListenerRegistry::exists(DataTypeID dtid) const
void Dispatcher::ListenerRegistry::cleanup(MonotonicTime ts)
{
TransferListenerBase* p = list_.get();
TransferListener* p = list_.get();
while (p)
{
TransferListenerBase* const next = p->getNextListNode();
TransferListener* const next = p->getNextListNode();
p->cleanup(ts); // p may be modified
p = next;
}
@ -123,10 +123,10 @@ void Dispatcher::ListenerRegistry::cleanup(MonotonicTime ts)
void Dispatcher::ListenerRegistry::handleFrame(const RxFrame& frame)
{
TransferListenerBase* p = list_.get();
TransferListener* p = list_.get();
while (p)
{
TransferListenerBase* const next = p->getNextListNode();
TransferListener* const next = p->getNextListNode();
if (p->getDataTypeDescriptor().getID() == frame.getDataTypeID())
{
p->handleFrame(frame); // p may be modified
@ -311,7 +311,7 @@ void Dispatcher::cleanup(MonotonicTime ts)
lsrv_resp_.cleanup(ts);
}
bool Dispatcher::registerMessageListener(TransferListenerBase* listener)
bool Dispatcher::registerMessageListener(TransferListener* listener)
{
if (listener->getDataTypeDescriptor().getKind() != DataTypeKindMessage)
{
@ -321,7 +321,7 @@ bool Dispatcher::registerMessageListener(TransferListenerBase* listener)
return lmsg_.add(listener, ListenerRegistry::ManyListeners); // Multiple subscribers are OK
}
bool Dispatcher::registerServiceRequestListener(TransferListenerBase* listener)
bool Dispatcher::registerServiceRequestListener(TransferListener* listener)
{
if (listener->getDataTypeDescriptor().getKind() != DataTypeKindService)
{
@ -331,7 +331,7 @@ bool Dispatcher::registerServiceRequestListener(TransferListenerBase* listener)
return lsrv_req_.add(listener, ListenerRegistry::UniqueListener); // Only one server per data type
}
bool Dispatcher::registerServiceResponseListener(TransferListenerBase* listener)
bool Dispatcher::registerServiceResponseListener(TransferListener* listener)
{
if (listener->getDataTypeDescriptor().getKind() != DataTypeKindService)
{
@ -341,17 +341,17 @@ bool Dispatcher::registerServiceResponseListener(TransferListenerBase* listener)
return lsrv_resp_.add(listener, ListenerRegistry::ManyListeners); // Multiple callers may call same srv
}
void Dispatcher::unregisterMessageListener(TransferListenerBase* listener)
void Dispatcher::unregisterMessageListener(TransferListener* listener)
{
lmsg_.remove(listener);
}
void Dispatcher::unregisterServiceRequestListener(TransferListenerBase* listener)
void Dispatcher::unregisterServiceRequestListener(TransferListener* listener)
{
lsrv_req_.remove(listener);
}
void Dispatcher::unregisterServiceResponseListener(TransferListenerBase* listener)
void Dispatcher::unregisterServiceResponseListener(TransferListener* listener)
{
lsrv_resp_.remove(listener);
}

View File

@ -8,6 +8,58 @@
namespace uavcan
{
/*
* StaticTransferBufferImpl
*/
int StaticTransferBufferImpl::read(unsigned offset, uint8_t* data, unsigned len) const
{
if (!data)
{
UAVCAN_ASSERT(0);
return -ErrInvalidParam;
}
if (offset >= max_write_pos_)
{
return 0;
}
if ((offset + len) > max_write_pos_)
{
len = max_write_pos_ - offset;
}
UAVCAN_ASSERT((offset + len) <= max_write_pos_);
(void)copy(data_ + offset, data_ + offset + len, data);
return int(len);
}
int StaticTransferBufferImpl::write(unsigned offset, const uint8_t* data, unsigned len)
{
if (!data)
{
UAVCAN_ASSERT(0);
return -ErrInvalidParam;
}
if (offset >= size_)
{
return 0;
}
if ((offset + len) > size_)
{
len = size_ - offset;
}
UAVCAN_ASSERT((offset + len) <= size_);
(void)copy(data, data + len, data_ + offset);
max_write_pos_ = max(uint16_t(offset + len), uint16_t(max_write_pos_));
return int(len);
}
void StaticTransferBufferImpl::reset()
{
max_write_pos_ = 0;
#if UAVCAN_DEBUG
fill(data_, data_ + size_, uint8_t(0));
#endif
}
/*
* TransferBufferManagerKey
*/
@ -23,8 +75,8 @@ std::string TransferBufferManagerKey::toString() const
/*
* DynamicTransferBuffer::Block
*/
DynamicTransferBufferManagerEntry::Block*
DynamicTransferBufferManagerEntry::Block::instantiate(IPoolAllocator& allocator)
TransferBufferManagerEntry::Block*
TransferBufferManagerEntry::Block::instantiate(IPoolAllocator& allocator)
{
void* const praw = allocator.allocate(sizeof(Block));
if (praw == NULL)
@ -34,7 +86,7 @@ DynamicTransferBufferManagerEntry::Block::instantiate(IPoolAllocator& allocator)
return new (praw) Block;
}
void DynamicTransferBufferManagerEntry::Block::destroy(Block*& obj, IPoolAllocator& allocator)
void TransferBufferManagerEntry::Block::destroy(Block*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{
@ -44,8 +96,8 @@ void DynamicTransferBufferManagerEntry::Block::destroy(Block*& obj, IPoolAllocat
}
}
void DynamicTransferBufferManagerEntry::Block::read(uint8_t*& outptr, unsigned target_offset,
unsigned& total_offset, unsigned& left_to_read)
void TransferBufferManagerEntry::Block::read(uint8_t*& outptr, unsigned target_offset,
unsigned& total_offset, unsigned& left_to_read)
{
UAVCAN_ASSERT(outptr);
for (unsigned i = 0; (i < Block::Size) && (left_to_read > 0); i++, total_offset++)
@ -58,7 +110,7 @@ void DynamicTransferBufferManagerEntry::Block::read(uint8_t*& outptr, unsigned t
}
}
void DynamicTransferBufferManagerEntry::Block::write(const uint8_t*& inptr, unsigned target_offset,
void TransferBufferManagerEntry::Block::write(const uint8_t*& inptr, unsigned target_offset,
unsigned& total_offset, unsigned& left_to_write)
{
UAVCAN_ASSERT(inptr);
@ -75,46 +127,28 @@ void DynamicTransferBufferManagerEntry::Block::write(const uint8_t*& inptr, unsi
/*
* DynamicTransferBuffer
*/
DynamicTransferBufferManagerEntry* DynamicTransferBufferManagerEntry::instantiate(IPoolAllocator& allocator,
TransferBufferManagerEntry* TransferBufferManagerEntry::instantiate(IPoolAllocator& allocator,
uint16_t max_size)
{
void* const praw = allocator.allocate(sizeof(DynamicTransferBufferManagerEntry));
void* const praw = allocator.allocate(sizeof(TransferBufferManagerEntry));
if (praw == NULL)
{
return NULL;
}
return new (praw) DynamicTransferBufferManagerEntry(allocator, max_size);
return new (praw) TransferBufferManagerEntry(allocator, max_size);
}
void DynamicTransferBufferManagerEntry::destroy(DynamicTransferBufferManagerEntry*& obj, IPoolAllocator& allocator)
void TransferBufferManagerEntry::destroy(TransferBufferManagerEntry*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{
obj->~DynamicTransferBufferManagerEntry();
obj->~TransferBufferManagerEntry();
allocator.deallocate(obj);
obj = NULL;
}
}
void DynamicTransferBufferManagerEntry::doReset()
{
max_write_pos_ = 0;
Block* p = blocks_.get();
while (p)
{
Block* const next = p->getNextListNode();
blocks_.remove(p);
Block::destroy(p, allocator_);
p = next;
}
}
void DynamicTransferBufferManagerEntry::resetImpl()
{
doReset();
}
int DynamicTransferBufferManagerEntry::read(unsigned offset, uint8_t* data, unsigned len) const
int TransferBufferManagerEntry::read(unsigned offset, uint8_t* data, unsigned len) const
{
if (!data)
{
@ -150,7 +184,7 @@ int DynamicTransferBufferManagerEntry::read(unsigned offset, uint8_t* data, unsi
return int(len);
}
int DynamicTransferBufferManagerEntry::write(unsigned offset, const uint8_t* data, unsigned len)
int TransferBufferManagerEntry::write(unsigned offset, const uint8_t* data, unsigned len)
{
if (!data)
{
@ -221,82 +255,26 @@ int DynamicTransferBufferManagerEntry::write(unsigned offset, const uint8_t* dat
return int(actually_written);
}
/*
* StaticTransferBufferImpl
*/
int StaticTransferBufferImpl::read(unsigned offset, uint8_t* data, unsigned len) const
{
if (!data)
{
UAVCAN_ASSERT(0);
return -ErrInvalidParam;
}
if (offset >= max_write_pos_)
{
return 0;
}
if ((offset + len) > max_write_pos_)
{
len = max_write_pos_ - offset;
}
UAVCAN_ASSERT((offset + len) <= max_write_pos_);
(void)copy(data_ + offset, data_ + offset + len, data);
return int(len);
}
int StaticTransferBufferImpl::write(unsigned offset, const uint8_t* data, unsigned len)
{
if (!data)
{
UAVCAN_ASSERT(0);
return -ErrInvalidParam;
}
if (offset >= size_)
{
return 0;
}
if ((offset + len) > size_)
{
len = size_ - offset;
}
UAVCAN_ASSERT((offset + len) <= size_);
(void)copy(data, data + len, data_ + offset);
max_write_pos_ = max(uint16_t(offset + len), uint16_t(max_write_pos_));
return int(len);
}
void StaticTransferBufferImpl::reset()
void TransferBufferManagerEntry::reset(const TransferBufferManagerKey& key)
{
key_ = key;
max_write_pos_ = 0;
#if UAVCAN_DEBUG
fill(data_, data_ + size_, uint8_t(0));
#endif
Block* p = blocks_.get();
while (p)
{
Block* const next = p->getNextListNode();
blocks_.remove(p);
Block::destroy(p, allocator_);
p = next;
}
}
/*
* StaticTransferBufferManagerEntryImpl
* TransferBufferManager
*/
void StaticTransferBufferManagerEntryImpl::resetImpl()
TransferBufferManagerEntry* TransferBufferManager::findFirst(const TransferBufferManagerKey& key)
{
buf_.reset();
}
int StaticTransferBufferManagerEntryImpl::read(unsigned offset, uint8_t* data, unsigned len) const
{
return buf_.read(offset, data, len);
}
int StaticTransferBufferManagerEntryImpl::write(unsigned offset, const uint8_t* data, unsigned len)
{
return buf_.write(offset, data, len);
}
/*
* TransferBufferManagerImpl
*/
DynamicTransferBufferManagerEntry* TransferBufferManagerImpl::findFirstDynamic(const TransferBufferManagerKey& key)
{
DynamicTransferBufferManagerEntry* dyn = dynamic_buffers_.get();
TransferBufferManagerEntry* dyn = buffers_.get();
while (dyn)
{
UAVCAN_ASSERT(!dyn->isEmpty());
@ -309,29 +287,29 @@ DynamicTransferBufferManagerEntry* TransferBufferManagerImpl::findFirstDynamic(c
return NULL;
}
TransferBufferManagerImpl::~TransferBufferManagerImpl()
TransferBufferManager::~TransferBufferManager()
{
DynamicTransferBufferManagerEntry* dyn = dynamic_buffers_.get();
TransferBufferManagerEntry* dyn = buffers_.get();
while (dyn)
{
DynamicTransferBufferManagerEntry* const next = dyn->getNextListNode();
dynamic_buffers_.remove(dyn);
DynamicTransferBufferManagerEntry::destroy(dyn, allocator_);
TransferBufferManagerEntry* const next = dyn->getNextListNode();
buffers_.remove(dyn);
TransferBufferManagerEntry::destroy(dyn, allocator_);
dyn = next;
}
}
ITransferBuffer* TransferBufferManagerImpl::access(const TransferBufferManagerKey& key)
ITransferBuffer* TransferBufferManager::access(const TransferBufferManagerKey& key)
{
if (key.isEmpty())
{
UAVCAN_ASSERT(0);
return NULL;
}
return findFirstDynamic(key);
return findFirst(key);
}
ITransferBuffer* TransferBufferManagerImpl::create(const TransferBufferManagerKey& key)
ITransferBuffer* TransferBufferManager::create(const TransferBufferManagerKey& key)
{
if (key.isEmpty())
{
@ -340,13 +318,13 @@ ITransferBuffer* TransferBufferManagerImpl::create(const TransferBufferManagerKe
}
remove(key);
DynamicTransferBufferManagerEntry* tbme = DynamicTransferBufferManagerEntry::instantiate(allocator_, max_buf_size_);
TransferBufferManagerEntry* tbme = TransferBufferManagerEntry::instantiate(allocator_, max_buf_size_);
if (tbme == NULL)
{
return NULL; // Epic fail.
}
dynamic_buffers_.insert(tbme);
buffers_.insert(tbme);
UAVCAN_TRACE("TransferBufferManager", "Buffer created [num=%u], %s", getNumBuffers(), key.toString().c_str());
@ -358,27 +336,27 @@ ITransferBuffer* TransferBufferManagerImpl::create(const TransferBufferManagerKe
return tbme;
}
void TransferBufferManagerImpl::remove(const TransferBufferManagerKey& key)
void TransferBufferManager::remove(const TransferBufferManagerKey& key)
{
UAVCAN_ASSERT(!key.isEmpty());
DynamicTransferBufferManagerEntry* dyn = findFirstDynamic(key);
TransferBufferManagerEntry* dyn = findFirst(key);
if (dyn != NULL)
{
UAVCAN_TRACE("TransferBufferManager", "Buffer deleted, %s", key.toString().c_str());
dynamic_buffers_.remove(dyn);
DynamicTransferBufferManagerEntry::destroy(dyn, allocator_);
buffers_.remove(dyn);
TransferBufferManagerEntry::destroy(dyn, allocator_);
}
}
bool TransferBufferManagerImpl::isEmpty() const
bool TransferBufferManager::isEmpty() const
{
return getNumBuffers() == 0;
}
unsigned TransferBufferManagerImpl::getNumBuffers() const
unsigned TransferBufferManager::getNumBuffers() const
{
return dynamic_buffers_.getLength();
return buffers_.getLength();
}
}

View File

@ -80,10 +80,10 @@ int MultiFrameIncomingTransfer::read(unsigned offset, uint8_t* data, unsigned le
}
/*
* TransferListenerBase::TimedOutReceiverPredicate
* TransferListener::TimedOutReceiverPredicate
*/
bool TransferListenerBase::TimedOutReceiverPredicate::operator()(const TransferBufferManagerKey& key,
const TransferReceiver& value) const
bool TransferListener::TimedOutReceiverPredicate::operator()(const TransferBufferManagerKey& key,
const TransferReceiver& value) const
{
if (value.isTimedOut(ts_))
{
@ -101,9 +101,9 @@ bool TransferListenerBase::TimedOutReceiverPredicate::operator()(const TransferB
}
/*
* TransferListenerBase
* TransferListener
*/
bool TransferListenerBase::checkPayloadCrc(const uint16_t compare_with, const ITransferBuffer& tbb) const
bool TransferListener::checkPayloadCrc(const uint16_t compare_with, const ITransferBuffer& tbb) const
{
TransferCRC crc = crc_base_;
unsigned offset = 0;
@ -113,7 +113,7 @@ bool TransferListenerBase::checkPayloadCrc(const uint16_t compare_with, const IT
const int res = tbb.read(offset, buf, sizeof(buf));
if (res < 0)
{
UAVCAN_TRACE("TransferListenerBase", "Failed to check CRC: Buffer read failure %i", res);
UAVCAN_TRACE("TransferListener", "Failed to check CRC: Buffer read failure %i", res);
return false;
}
if (res == 0)
@ -125,14 +125,14 @@ bool TransferListenerBase::checkPayloadCrc(const uint16_t compare_with, const IT
}
if (crc.get() != compare_with)
{
UAVCAN_TRACE("TransferListenerBase", "CRC mismatch, expected=0x%04x, got=0x%04x",
UAVCAN_TRACE("TransferListener", "CRC mismatch, expected=0x%04x, got=0x%04x",
int(compare_with), int(crc.get()));
return false;
}
return true;
}
void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxFrame& frame,
void TransferListener::handleReception(TransferReceiver& receiver, const RxFrame& frame,
TransferBufferAccessor& tba)
{
switch (receiver.addFrame(frame, tba))
@ -155,12 +155,12 @@ void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxF
const ITransferBuffer* tbb = tba.access();
if (tbb == NULL)
{
UAVCAN_TRACE("TransferListenerBase", "Buffer access failure, last frame: %s", frame.toString().c_str());
UAVCAN_TRACE("TransferListener", "Buffer access failure, last frame: %s", frame.toString().c_str());
break;
}
if (!checkPayloadCrc(receiver.getLastTransferCrc(), *tbb))
{
UAVCAN_TRACE("TransferListenerBase", "CRC error, last frame: %s", frame.toString().c_str());
UAVCAN_TRACE("TransferListener", "CRC error, last frame: %s", frame.toString().c_str());
break;
}
MultiFrameIncomingTransfer it(receiver.getLastTransferTimestampMonotonic(),
@ -177,7 +177,7 @@ void TransferListenerBase::handleReception(TransferReceiver& receiver, const RxF
}
}
void TransferListenerBase::handleAnonymousTransferReception(const RxFrame& frame)
void TransferListener::handleAnonymousTransferReception(const RxFrame& frame)
{
if (allow_anonymous_transfers_)
{
@ -187,13 +187,13 @@ void TransferListenerBase::handleAnonymousTransferReception(const RxFrame& frame
}
}
void TransferListenerBase::cleanup(MonotonicTime ts)
void TransferListener::cleanup(MonotonicTime ts)
{
receivers_.removeAllWhere(TimedOutReceiverPredicate(ts, bufmgr_));
UAVCAN_ASSERT(receivers_.isEmpty() ? bufmgr_.isEmpty() : 1);
}
void TransferListenerBase::handleFrame(const RxFrame& frame)
void TransferListener::handleFrame(const RxFrame& frame)
{
if (frame.getSrcNodeID().isUnicast()) // Normal transfer
{
@ -227,7 +227,25 @@ void TransferListenerBase::handleFrame(const RxFrame& frame)
}
else
{
UAVCAN_TRACE("TransferListenerBase", "Invalid frame: %s", frame.toString().c_str()); // Invalid frame
UAVCAN_TRACE("TransferListener", "Invalid frame: %s", frame.toString().c_str()); // Invalid frame
}
}
/*
* TransferListenerWithFilter
*/
void TransferListenerWithFilter::handleFrame(const RxFrame& frame)
{
if (filter_ != NULL)
{
if (filter_->shouldAcceptFrame(frame))
{
TransferListener::handleFrame(frame);
}
}
else
{
UAVCAN_ASSERT(0);
}
}

View File

@ -86,17 +86,17 @@ TEST(Dispatcher, Reception)
makeDataType(uavcan::DataTypeKindService, 1)
};
typedef TestListener<512> Subscriber;
typedef std::auto_ptr<Subscriber> SubscriberPtr;
static const int NUM_SUBSCRIBERS = 6;
SubscriberPtr subscribers[NUM_SUBSCRIBERS] =
typedef std::auto_ptr<TestListener> TestListenerPtr;
static const int MaxBufSize = 512;
static const int NumSubscribers = 6;
TestListenerPtr subscribers[NumSubscribers] =
{
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[0], pool)), // msg
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[0], pool)), // msg // Two similar
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[1], pool)), // msg
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[2], pool)), // srv
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[3], pool)), // srv
SubscriberPtr(new Subscriber(dispatcher.getTransferPerfCounter(), TYPES[3], pool)) // srv // Repeat again
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[0], MaxBufSize, pool)), // msg
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[0], MaxBufSize, pool)), // msg // Two similar
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[1], MaxBufSize, pool)), // msg
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[2], MaxBufSize, pool)), // srv
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[3], MaxBufSize, pool)), // srv
TestListenerPtr(new TestListener(dispatcher.getTransferPerfCounter(), TYPES[3], MaxBufSize, pool)) // srv // Repeat again
};
static const std::string DATA[6] =
@ -139,7 +139,7 @@ TEST(Dispatcher, Reception)
/*
* Registration
*/
for (int i = 0; i < NUM_SUBSCRIBERS; i++)
for (int i = 0; i < NumSubscribers; i++)
{
ASSERT_FALSE(dispatcher.hasSubscriber(subscribers[i]->getDataTypeDescriptor().getID()));
ASSERT_FALSE(dispatcher.hasPublisher(subscribers[i]->getDataTypeDescriptor().getID()));
@ -153,7 +153,7 @@ TEST(Dispatcher, Reception)
ASSERT_TRUE(dispatcher.registerServiceResponseListener(subscribers[4].get()));
ASSERT_TRUE(dispatcher.registerServiceResponseListener(subscribers[5].get()));
for (int i = 0; i < NUM_SUBSCRIBERS; i++)
for (int i = 0; i < NumSubscribers; i++)
{
ASSERT_FALSE(dispatcher.hasPublisher(subscribers[i]->getDataTypeDescriptor().getID()));
}
@ -177,7 +177,7 @@ TEST(Dispatcher, Reception)
ASSERT_EQ(1, dispatcher.getNumServiceRequestListeners());
ASSERT_EQ(2, dispatcher.getNumServiceResponseListeners());
for (int i = 0; i < NUM_SUBSCRIBERS; i++)
for (int i = 0; i < NumSubscribers; i++)
{
ASSERT_TRUE(subscribers[i]->isEmpty());
}
@ -214,7 +214,7 @@ TEST(Dispatcher, Reception)
ASSERT_TRUE(subscribers[5]->matchAndPop(transfers[3]));
for (int i = 0; i < NUM_SUBSCRIBERS; i++)
for (int i = 0; i < NumSubscribers; i++)
{
ASSERT_TRUE(subscribers[i]->isEmpty());
}

View File

@ -73,7 +73,7 @@ TEST(MultiFrameIncomingTransfer, Basic)
using uavcan::MultiFrameIncomingTransfer;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> poolmgr;
uavcan::TransferBufferManager<256> bufmgr(poolmgr);
uavcan::TransferBufferManager bufmgr(256, poolmgr);
const RxFrame frame = makeFrame();
uavcan::TransferBufferManagerKey bufmgr_key(frame.getSrcNodeID(), frame.getTransferType());

View File

@ -83,8 +83,8 @@ static const int TEST_BUFFER_SIZE = 200;
TEST(StaticTransferBuffer, Basic)
{
using uavcan::StaticTransferBufferManagerEntry;
StaticTransferBufferManagerEntry<TEST_BUFFER_SIZE> buf;
using uavcan::StaticTransferBuffer;
StaticTransferBuffer<TEST_BUFFER_SIZE> buf;
uint8_t local_buffer[TEST_BUFFER_SIZE * 2];
const uint8_t* const test_data_ptr = reinterpret_cast<const uint8_t*>(TEST_DATA.c_str());
@ -126,15 +126,15 @@ TEST(StaticTransferBuffer, Basic)
}
TEST(DynamicTransferBufferManagerEntry, Basic)
TEST(TransferBufferManagerEntry, Basic)
{
using uavcan::DynamicTransferBufferManagerEntry;
using uavcan::TransferBufferManagerEntry;
static const int MAX_SIZE = TEST_BUFFER_SIZE;
static const int POOL_BLOCKS = 8;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * POOL_BLOCKS, uavcan::MemPoolBlockSize> pool;
DynamicTransferBufferManagerEntry buf(pool, MAX_SIZE);
TransferBufferManagerEntry buf(pool, MAX_SIZE);
uint8_t local_buffer[TEST_BUFFER_SIZE * 2];
const uint8_t* const test_data_ptr = reinterpret_cast<const uint8_t*>(TEST_DATA.c_str());
@ -186,7 +186,7 @@ TEST(DynamicTransferBufferManagerEntry, Basic)
// Destroying the object; memory should be released
ASSERT_LT(0, pool.getNumUsedBlocks());
buf.~DynamicTransferBufferManagerEntry();
buf.~TransferBufferManagerEntry();
ASSERT_EQ(0, pool.getNumUsedBlocks());
}
@ -232,8 +232,7 @@ TEST(TransferBufferManager, Basic)
static const int POOL_BLOCKS = 100;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * POOL_BLOCKS, uavcan::MemPoolBlockSize> pool;
typedef TransferBufferManager<MGR_MAX_BUFFER_SIZE> TransferBufferManagerType;
std::auto_ptr<TransferBufferManagerType> mgr(new TransferBufferManagerType(pool));
std::auto_ptr<TransferBufferManager> mgr(new TransferBufferManager(MGR_MAX_BUFFER_SIZE, pool));
// Empty
ASSERT_FALSE(mgr->access(TransferBufferManagerKey(0, uavcan::TransferTypeMessageBroadcast)));
@ -313,11 +312,3 @@ TEST(TransferBufferManager, Basic)
mgr.reset();
ASSERT_EQ(0, pool.getNumUsedBlocks());
}
TEST(TransferBufferManager, EmptySpecialization)
{
uavcan::TransferBufferManager<0> mgr;
(void)mgr;
ASSERT_GE(sizeof(void*), sizeof(mgr));
}

View File

@ -9,11 +9,11 @@
class TransferListenerEmulator : public IncomingTransferEmulatorBase
{
uavcan::TransferListenerBase& target_;
uavcan::TransferListener& target_;
const uavcan::DataTypeDescriptor data_type_;
public:
TransferListenerEmulator(uavcan::TransferListenerBase& target, const uavcan::DataTypeDescriptor& type,
TransferListenerEmulator(uavcan::TransferListener& target, const uavcan::DataTypeDescriptor& type,
uavcan::NodeID dst_node_id = 127)
: IncomingTransferEmulatorBase(dst_node_id)
, target_(target)
@ -38,7 +38,7 @@ TEST(TransferListener, BasicMFT)
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> pool;
uavcan::TransferPerfCounter perf;
TestListener<256> subscriber(perf, type, pool);
TestListener subscriber(perf, type, 256, pool);
/*
* Test data
@ -96,7 +96,7 @@ TEST(TransferListener, CrcFailure)
static const int NUM_POOL_BLOCKS = 100;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
uavcan::TransferPerfCounter perf;
TestListener<256> subscriber(perf, type, poolmgr); // Static buffer only, 2 entries
TestListener subscriber(perf, type, 256, poolmgr); // Static buffer only, 2 entries
/*
* Generating transfers with damaged payload (CRC is not valid)
@ -140,7 +140,7 @@ TEST(TransferListener, BasicSFT)
static const int NUM_POOL_BLOCKS = 100;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
uavcan::TransferPerfCounter perf;
TestListener<0> subscriber(perf, type, poolmgr); // Max buf size is 0, i.e. SFT-only
TestListener subscriber(perf, type, 0, poolmgr); // Max buf size is 0, i.e. SFT-only
TransferListenerEmulator emulator(subscriber, type);
const Transfer transfers[] =
@ -176,7 +176,7 @@ TEST(TransferListener, Cleanup)
static const int NUM_POOL_BLOCKS = 100;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
uavcan::TransferPerfCounter perf;
TestListener<256> subscriber(perf, type, poolmgr); // Static buffer only, 1 entry
TestListener subscriber(perf, type, 256, poolmgr);
/*
* Generating transfers
@ -208,7 +208,7 @@ TEST(TransferListener, Cleanup)
/*
* Cleanup with huge timestamp value will remove all entries
*/
static_cast<uavcan::TransferListenerBase&>(subscriber).cleanup(tsMono(100000000));
static_cast<uavcan::TransferListener&>(subscriber).cleanup(tsMono(100000000));
/*
* Sending the same transfers again - they will be accepted since registres were cleared
@ -232,7 +232,7 @@ TEST(TransferListener, AnonymousTransfers)
static const int NUM_POOL_BLOCKS = 100;
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * NUM_POOL_BLOCKS, uavcan::MemPoolBlockSize> poolmgr;
uavcan::TransferPerfCounter perf;
TestListener<0> subscriber(perf, type, poolmgr);
TestListener subscriber(perf, type, 0, poolmgr);
TransferListenerEmulator emulator(subscriber, type);
const Transfer transfers[] =
@ -264,5 +264,5 @@ TEST(TransferListener, Sizes)
{
using namespace uavcan;
std::cout << "sizeof(TransferListener<64>): " << sizeof(TransferListener<64>) << std::endl;
std::cout << "sizeof(TransferListener): " << sizeof(TransferListener) << std::endl;
}

View File

@ -76,10 +76,10 @@ struct Context
{
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 100, uavcan::MemPoolBlockSize> pool;
uavcan::TransferReceiver receiver; // Must be default constructible and copyable
uavcan::TransferBufferManager<BufSize> bufmgr;
uavcan::TransferBufferManager bufmgr;
Context() :
bufmgr(pool)
bufmgr(BufSize, pool)
{ }
~Context()
@ -122,7 +122,7 @@ TEST(TransferReceiver, Basic)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
std::cout << "sizeof(TransferReceiver): " << sizeof(TransferReceiver) << std::endl;
@ -261,7 +261,7 @@ TEST(TransferReceiver, OutOfBufferSpace_32bytes)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
/*
@ -299,7 +299,7 @@ TEST(TransferReceiver, OutOfOrderFrames)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
CHECK_NOT_COMPLETE(rcv.addFrame(gen(1, "1234567", SET100, 7, 100000000), bk));
@ -323,7 +323,7 @@ TEST(TransferReceiver, IntervalMeasurement)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
static const int INTERVAL = 1000;
@ -353,7 +353,7 @@ TEST(TransferReceiver, Restart)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
/*
@ -401,7 +401,7 @@ TEST(TransferReceiver, UtcTransferTimestamping)
Context<32> context;
RxFrameGenerator gen(789);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferAccessor bk(context.bufmgr, RxFrameGenerator::DEFAULT_KEY);
/*
@ -460,7 +460,7 @@ TEST(TransferReceiver, HeaderParsing)
Context<32> context;
RxFrameGenerator gen(123);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
/*
* MFT, message broadcasting
@ -507,7 +507,7 @@ TEST(TransferReceiver, HeaderParsing)
Context<32> context;
RxFrameGenerator gen(123);
uavcan::TransferReceiver& rcv = context.receiver;
uavcan::ITransferBufferManager& bufmgr = context.bufmgr;
uavcan::TransferBufferManager& bufmgr = context.bufmgr;
static const uavcan::TransferType ADDRESSED_TRANSFER_TYPES[2] =
{

View File

@ -123,9 +123,9 @@ TEST(TransferSender, Basic)
}
}
TestListener<512> sub_msg(dispatcher_rx.getTransferPerfCounter(), TYPES[0], poolmgr);
TestListener<512> sub_srv_req(dispatcher_rx.getTransferPerfCounter(), TYPES[1], poolmgr);
TestListener<512> sub_srv_resp(dispatcher_rx.getTransferPerfCounter(), TYPES[1], poolmgr);
TestListener sub_msg(dispatcher_rx.getTransferPerfCounter(), TYPES[0], 512, poolmgr);
TestListener sub_srv_req(dispatcher_rx.getTransferPerfCounter(), TYPES[1], 512, poolmgr);
TestListener sub_srv_resp(dispatcher_rx.getTransferPerfCounter(), TYPES[1], 512, poolmgr);
dispatcher_rx.registerMessageListener(&sub_msg);
dispatcher_rx.registerServiceRequestListener(&sub_srv_req);

View File

@ -11,7 +11,7 @@ TEST(TransferTestHelpers, Transfer)
{
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * 8, uavcan::MemPoolBlockSize> pool;
uavcan::TransferBufferManager<128> mgr(pool);
uavcan::TransferBufferManager mgr(128, pool);
uavcan::TransferBufferAccessor tba(mgr, uavcan::TransferBufferManagerKey(0, uavcan::TransferTypeMessageBroadcast));
uavcan::RxFrame frame(uavcan::Frame(123, uavcan::TransferTypeMessageBroadcast, 1, 0, 0),

View File

@ -117,17 +117,16 @@ struct Transfer
* In reality, uavcan::TransferListener should accept only specific transfer types
* which are dispatched/filtered by uavcan::Dispatcher.
*/
template <unsigned MAX_BUF_SIZE>
class TestListener : public uavcan::TransferListener<MAX_BUF_SIZE>
class TestListener : public uavcan::TransferListener
{
typedef uavcan::TransferListener<MAX_BUF_SIZE> Base;
typedef uavcan::TransferListener Base;
std::queue<Transfer> transfers_;
public:
TestListener(uavcan::TransferPerfCounter& perf, const uavcan::DataTypeDescriptor& data_type,
uavcan::IPoolAllocator& allocator)
: Base(perf, data_type, allocator)
uavcan::uint16_t max_buffer_size, uavcan::IPoolAllocator& allocator)
: Base(perf, data_type, max_buffer_size, allocator)
{ }
void handleIncomingTransfer(uavcan::IncomingTransfer& transfer)
@ -166,7 +165,7 @@ public:
return res;
}
int getNumReceivedTransfers() const { return transfers_.size(); }
unsigned getNumReceivedTransfers() const { return static_cast<unsigned>(transfers_.size()); }
bool isEmpty() const { return transfers_.empty(); }
};