Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: UAVCAN UAVCAN_Subscriber
libuavcan/include/uavcan/transport/transfer_buffer.hpp
- Committer:
- RuslanUrya
- Date:
- 2018-04-14
- Revision:
- 0:dfe6edabb8ec
File content as of revision 0:dfe6edabb8ec:
/* * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> */ #ifndef UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED #define UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED #include <uavcan/std.hpp> #include <uavcan/error.hpp> #include <uavcan/transport/frame.hpp> #include <uavcan/transport/abstract_transfer_buffer.hpp> #include <uavcan/util/linked_list.hpp> #include <uavcan/dynamic_memory.hpp> #include <uavcan/build_config.hpp> #include <uavcan/debug.hpp> 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 */ class UAVCAN_EXPORT TransferBufferManagerKey { NodeID node_id_; uint8_t transfer_type_; public: TransferBufferManagerKey() : transfer_type_(TransferType(0)) { UAVCAN_ASSERT(isEmpty()); } TransferBufferManagerKey(NodeID node_id, TransferType ttype) : node_id_(node_id) , transfer_type_(ttype) { UAVCAN_ASSERT(!isEmpty()); } bool operator==(const TransferBufferManagerKey& rhs) const { return node_id_ == rhs.node_id_ && transfer_type_ == rhs.transfer_type_; } bool isEmpty() const { return !node_id_.isValid(); } NodeID getNodeID() const { return node_id_; } TransferType getTransferType() const { return TransferType(transfer_type_); } #if UAVCAN_TOSTRING std::string toString() const; #endif }; /** * Resizable gather/scatter storage. * reset() call releases all memory blocks. * Supports unordered write operations - from higher to lower offsets */ class UAVCAN_EXPORT TransferBufferManagerEntry : public ITransferBuffer , public LinkedListNode<TransferBufferManagerEntry> { struct Block : LinkedListNode<Block> { enum { Size = MemPoolBlockSize - sizeof(LinkedListNode<Block>) }; uint8_t data[static_cast<unsigned>(Size)]; static Block* instantiate(IPoolAllocator& allocator); static void destroy(Block*& obj, IPoolAllocator& allocator); void read(uint8_t*& outptr, unsigned target_offset, unsigned& total_offset, unsigned& left_to_read); void write(const uint8_t*& inptr, unsigned target_offset, unsigned& total_offset, unsigned& left_to_write); }; IPoolAllocator& allocator_; LinkedListRoot<Block> blocks_; // Blocks are ordered from lower to higher buffer offset uint16_t max_write_pos_; const uint16_t max_size_; TransferBufferManagerKey key_; public: 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<TransferBufferManagerEntry>::check(); } virtual ~TransferBufferManagerEntry() { reset(); } 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(const TransferBufferManagerKey& key = TransferBufferManagerKey()); const TransferBufferManagerKey& getKey() const { return key_; } bool isEmpty() const { return key_.isEmpty(); } }; /** * Buffer manager implementation. */ class TransferBufferManager : public Noncopyable { LinkedListRoot<TransferBufferManagerEntry> buffers_; IPoolAllocator& allocator_; const uint16_t max_buf_size_; TransferBufferManagerEntry* findFirst(const TransferBufferManagerKey& key); public: TransferBufferManager(uint16_t max_buf_size, IPoolAllocator& allocator) : allocator_(allocator), max_buf_size_(max_buf_size) { } ~TransferBufferManager(); ITransferBuffer* access(const TransferBufferManagerKey& key); ITransferBuffer* create(const TransferBufferManagerKey& key); void remove(const TransferBufferManagerKey& key); bool isEmpty() const; unsigned getNumBuffers() const; }; /** * Convinience class. */ class UAVCAN_EXPORT TransferBufferAccessor { TransferBufferManager& bufmgr_; const TransferBufferManagerKey key_; public: TransferBufferAccessor(TransferBufferManager& bufmgr, TransferBufferManagerKey key) : bufmgr_(bufmgr), key_(key) { UAVCAN_ASSERT(!key.isEmpty()); } ITransferBuffer* access() { return bufmgr_.access(key_); } ITransferBuffer* create() { return bufmgr_.create(key_); } void remove() { bufmgr_.remove(key_); } }; } #endif // UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED