libuav original
Dependents: UAVCAN UAVCAN_Subscriber
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
Generated on Tue Jul 12 2022 17:17:35 by 1.7.2