libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers transfer_buffer.hpp Source File

transfer_buffer.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED
00006 #define UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED
00007 
00008 #include <uavcan/std.hpp>
00009 #include <uavcan/error.hpp>
00010 #include <uavcan/transport/frame.hpp>
00011 #include <uavcan/transport/abstract_transfer_buffer.hpp>
00012 #include <uavcan/util/linked_list.hpp>
00013 #include <uavcan/dynamic_memory.hpp>
00014 #include <uavcan/build_config.hpp>
00015 #include <uavcan/debug.hpp>
00016 
00017 namespace uavcan
00018 {
00019 /**
00020  * Standalone static buffer
00021  */
00022 class StaticTransferBufferImpl : public ITransferBuffer
00023 {
00024     uint8_t* const data_;
00025     const uint16_t size_;
00026     uint16_t max_write_pos_;
00027 
00028 public:
00029     StaticTransferBufferImpl(uint8_t* buf, uint16_t buf_size) :
00030         data_(buf),
00031         size_(buf_size),
00032         max_write_pos_(0)
00033     { }
00034 
00035     virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
00036     virtual int write(unsigned offset, const uint8_t* data, unsigned len);
00037 
00038     void reset();
00039 
00040     uint16_t getSize() const { return size_; }
00041 
00042     uint8_t* getRawPtr() { return data_; }
00043     const uint8_t* getRawPtr() const { return data_; }
00044 
00045     uint16_t getMaxWritePos() const { return max_write_pos_; }
00046     void setMaxWritePos(uint16_t value) { max_write_pos_ = value; }
00047 };
00048 
00049 template <uint16_t Size>
00050 class UAVCAN_EXPORT StaticTransferBuffer : public StaticTransferBufferImpl
00051 {
00052     uint8_t buffer_[Size];
00053 public:
00054     StaticTransferBuffer() : StaticTransferBufferImpl(buffer_, Size)
00055     {
00056         StaticAssert<(Size > 0)>::check();
00057     }
00058 };
00059 
00060 /**
00061  * Internal for TransferBufferManager
00062  */
00063 class UAVCAN_EXPORT TransferBufferManagerKey
00064 {
00065     NodeID node_id_;
00066     uint8_t transfer_type_;
00067 
00068 public:
00069     TransferBufferManagerKey()
00070         : transfer_type_(TransferType(0))
00071     {
00072         UAVCAN_ASSERT(isEmpty());
00073     }
00074 
00075     TransferBufferManagerKey(NodeID node_id, TransferType ttype)
00076         : node_id_(node_id)
00077         , transfer_type_(ttype)
00078     {
00079         UAVCAN_ASSERT(!isEmpty());
00080     }
00081 
00082     bool operator==(const TransferBufferManagerKey& rhs) const
00083     {
00084         return node_id_ == rhs.node_id_ && transfer_type_ == rhs.transfer_type_;
00085     }
00086 
00087     bool isEmpty() const { return !node_id_.isValid(); }
00088 
00089     NodeID getNodeID() const { return node_id_; }
00090     TransferType getTransferType() const { return TransferType(transfer_type_); }
00091 
00092 #if UAVCAN_TOSTRING
00093     std::string toString() const;
00094 #endif
00095 };
00096 
00097 /**
00098  * Resizable gather/scatter storage.
00099  * reset() call releases all memory blocks.
00100  * Supports unordered write operations - from higher to lower offsets
00101  */
00102 class UAVCAN_EXPORT TransferBufferManagerEntry : public ITransferBuffer
00103                                                , public LinkedListNode<TransferBufferManagerEntry>
00104 {
00105     struct Block : LinkedListNode<Block>
00106     {
00107         enum { Size = MemPoolBlockSize - sizeof(LinkedListNode<Block> ) };
00108         uint8_t data[static_cast<unsigned>(Size)];
00109 
00110         static Block* instantiate(IPoolAllocator& allocator);
00111         static void destroy(Block*& obj, IPoolAllocator& allocator);
00112 
00113         void read(uint8_t*& outptr, unsigned target_offset,
00114                   unsigned& total_offset, unsigned& left_to_read);
00115         void write(const uint8_t*& inptr, unsigned target_offset,
00116                    unsigned& total_offset, unsigned& left_to_write);
00117     };
00118 
00119     IPoolAllocator& allocator_;
00120     LinkedListRoot<Block>  blocks_;    // Blocks are ordered from lower to higher buffer offset
00121     uint16_t max_write_pos_;
00122     const uint16_t max_size_;
00123     TransferBufferManagerKey key_;
00124 
00125 public:
00126     TransferBufferManagerEntry(IPoolAllocator& allocator, uint16_t max_size) :
00127         allocator_(allocator),
00128         max_write_pos_(0),
00129         max_size_(max_size)
00130     {
00131         StaticAssert<(Block::Size > 8)>::check();
00132         IsDynamicallyAllocatable<Block>::check();
00133         IsDynamicallyAllocatable<TransferBufferManagerEntry>::check();
00134     }
00135 
00136     virtual ~TransferBufferManagerEntry() { reset(); }
00137 
00138     static TransferBufferManagerEntry* instantiate(IPoolAllocator& allocator, uint16_t max_size);
00139     static void destroy(TransferBufferManagerEntry*& obj, IPoolAllocator& allocator);
00140 
00141     virtual int read(unsigned offset, uint8_t* data, unsigned len) const;
00142     virtual int write(unsigned offset, const uint8_t* data, unsigned len);
00143 
00144     void reset(const TransferBufferManagerKey& key = TransferBufferManagerKey());
00145 
00146     const TransferBufferManagerKey& getKey() const { return key_; }
00147     bool isEmpty() const { return key_.isEmpty(); }
00148 };
00149 
00150 /**
00151  * Buffer manager implementation.
00152  */
00153 class TransferBufferManager : public Noncopyable
00154 {
00155     LinkedListRoot<TransferBufferManagerEntry>  buffers_;
00156     IPoolAllocator& allocator_;
00157     const uint16_t max_buf_size_;
00158 
00159     TransferBufferManagerEntry* findFirst(const TransferBufferManagerKey& key);
00160 
00161 public:
00162     TransferBufferManager(uint16_t max_buf_size, IPoolAllocator& allocator) :
00163         allocator_(allocator),
00164         max_buf_size_(max_buf_size)
00165     { }
00166 
00167     ~TransferBufferManager();
00168 
00169     ITransferBuffer* access(const TransferBufferManagerKey& key);
00170     ITransferBuffer* create(const TransferBufferManagerKey& key);
00171     void remove(const TransferBufferManagerKey& key);
00172     bool isEmpty() const;
00173 
00174     unsigned getNumBuffers() const;
00175 };
00176 
00177 /**
00178  * Convinience class.
00179  */
00180 class UAVCAN_EXPORT TransferBufferAccessor
00181 {
00182     TransferBufferManager& bufmgr_;
00183     const TransferBufferManagerKey key_;
00184 
00185 public:
00186     TransferBufferAccessor(TransferBufferManager& bufmgr, TransferBufferManagerKey key) :
00187         bufmgr_(bufmgr),
00188         key_(key)
00189     {
00190         UAVCAN_ASSERT(!key.isEmpty());
00191     }
00192     ITransferBuffer* access() { return bufmgr_.access(key_); }
00193     ITransferBuffer* create() { return bufmgr_.create(key_); }
00194     void remove() { bufmgr_.remove(key_); }
00195 };
00196 
00197 }
00198 
00199 #endif // UAVCAN_TRANSPORT_TRANSFER_BUFFER_HPP_INCLUDED