Dynamic memory refactoring: Entire library now uses IPoolAllocator instead of IAllocator, which was removed completely. This change was needed to enable TX queue constraints, see the next commits.

This commit is contained in:
Pavel Kirienko 2014-04-12 17:17:06 +04:00
parent 5808bfc0c9
commit 4e7287358a
14 changed files with 120 additions and 61 deletions

View File

@ -18,25 +18,23 @@ namespace uavcan
/**
* This interface is used by other library components that need dynamic memory.
*/
class UAVCAN_EXPORT IAllocator
class UAVCAN_EXPORT IPoolAllocator
{
public:
virtual ~IAllocator() { }
virtual ~IPoolAllocator() { }
virtual void* allocate(std::size_t size) = 0;
virtual void deallocate(const void* ptr) = 0;
};
class UAVCAN_EXPORT IPoolAllocator : public IAllocator
{
public:
virtual bool isInPool(const void* ptr) const = 0;
virtual std::size_t getBlockSize() const = 0;
virtual std::size_t getNumBlocks() const = 0;
};
template <int MaxPools>
class UAVCAN_EXPORT PoolManager : public IAllocator, Noncopyable
template <unsigned MaxPools>
class UAVCAN_EXPORT PoolManager : public IPoolAllocator, Noncopyable
{
IPoolAllocator* pools_[MaxPools];
@ -56,8 +54,12 @@ public:
bool addPool(IPoolAllocator* pool);
void* allocate(std::size_t size);
void deallocate(const void* ptr);
bool isInPool(const void* ptr) const;
std::size_t getBlockSize() const;
std::size_t getNumBlocks() const;
};
@ -80,32 +82,31 @@ class UAVCAN_EXPORT PoolAllocator : public IPoolAllocator, Noncopyable
} pool_;
public:
static const int NumBlocks = int(PoolSize / BlockSize);
static const unsigned NumBlocks = unsigned(PoolSize / BlockSize);
PoolAllocator();
void* allocate(std::size_t size);
void deallocate(const void* ptr);
bool isInPool(const void* ptr) const;
std::size_t getBlockSize() const { return BlockSize; }
std::size_t getNumBlocks() const { return NumBlocks; }
int getNumFreeBlocks() const;
int getNumUsedBlocks() const { return NumBlocks - getNumFreeBlocks(); }
unsigned getNumFreeBlocks() const;
unsigned getNumUsedBlocks() const { return NumBlocks - getNumFreeBlocks(); }
};
class LimitedPoolAllocator : public IAllocator
class LimitedPoolAllocator : public IPoolAllocator
{
IAllocator& allocator_;
IPoolAllocator& allocator_;
const std::size_t max_blocks_;
std::size_t used_blocks_;
public:
LimitedPoolAllocator(IAllocator& allocator, std::size_t max_blocks)
LimitedPoolAllocator(IPoolAllocator& allocator, std::size_t max_blocks)
: allocator_(allocator)
, max_blocks_(max_blocks)
, used_blocks_(0)
@ -115,6 +116,11 @@ public:
void* allocate(std::size_t size);
void deallocate(const void* ptr);
bool isInPool(const void* ptr) const;
std::size_t getBlockSize() const;
std::size_t getNumBlocks() const;
};
// ----------------------------------------------------------------------------
@ -122,12 +128,12 @@ public:
/*
* PoolManager<>
*/
template <int MaxPools>
template <unsigned MaxPools>
bool PoolManager<MaxPools>::addPool(IPoolAllocator* pool)
{
assert(pool);
bool retval = false;
for (int i = 0; i < MaxPools; i++)
for (unsigned i = 0; i < MaxPools; i++)
{
assert(pools_[i] != pool);
if (pools_[i] == NULL || pools_[i] == pool)
@ -142,10 +148,10 @@ bool PoolManager<MaxPools>::addPool(IPoolAllocator* pool)
return retval;
}
template <int MaxPools>
template <unsigned MaxPools>
void* PoolManager<MaxPools>::allocate(std::size_t size)
{
for (int i = 0; i < MaxPools; i++)
for (unsigned i = 0; i < MaxPools; i++)
{
if (pools_[i] == NULL)
{
@ -160,10 +166,10 @@ void* PoolManager<MaxPools>::allocate(std::size_t size)
return NULL;
}
template <int MaxPools>
template <unsigned MaxPools>
void PoolManager<MaxPools>::deallocate(const void* ptr)
{
for (int i = 0; i < MaxPools; i++)
for (unsigned i = 0; i < MaxPools; i++)
{
if (pools_[i] == NULL)
{
@ -178,6 +184,44 @@ void PoolManager<MaxPools>::deallocate(const void* ptr)
}
}
template <unsigned MaxPools>
bool PoolManager<MaxPools>::isInPool(const void* ptr) const
{
for (unsigned i = 0; i < MaxPools; i++)
{
if (pools_[i] == NULL)
{
break;
}
if (pools_[i]->isInPool(ptr))
{
return true;
}
}
return false;
}
template <unsigned MaxPools>
std::size_t PoolManager<MaxPools>::getBlockSize() const
{
return 0;
}
template <unsigned MaxPools>
std::size_t PoolManager<MaxPools>::getNumBlocks() const
{
std::size_t ret = 0;
for (unsigned i = 0; i < MaxPools; i++)
{
if (pools_[i] == NULL)
{
break;
}
ret += pools_[i]->getNumBlocks();
}
return ret;
}
/*
* PoolAllocator<>
*/
@ -186,7 +230,7 @@ PoolAllocator<PoolSize, BlockSize>::PoolAllocator()
: free_list_(reinterpret_cast<Node*>(pool_.bytes))
{
memset(pool_.bytes, 0, PoolSize);
for (int i = 0; i < NumBlocks - 1; i++)
for (unsigned i = 0; (i + 1) < (NumBlocks - 1 + 1); i++) // -Werror=type-limits
{
free_list_[i].next = free_list_ + i + 1;
}
@ -228,9 +272,9 @@ bool PoolAllocator<PoolSize, BlockSize>::isInPool(const void* ptr) const
}
template <std::size_t PoolSize, std::size_t BlockSize>
int PoolAllocator<PoolSize, BlockSize>::getNumFreeBlocks() const
unsigned PoolAllocator<PoolSize, BlockSize>::getNumFreeBlocks() const
{
int num = 0;
unsigned num = 0;
Node* p = free_list_;
while (p)
{

View File

@ -50,7 +50,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
IsDynamicallyAllocatable<KVGroup>::check();
}
static KVGroup* instantiate(IAllocator& allocator)
static KVGroup* instantiate(IPoolAllocator& allocator)
{
void* const praw = allocator.allocate(sizeof(KVGroup));
if (praw == NULL)
@ -60,7 +60,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
return new (praw) KVGroup();
}
static void destroy(KVGroup*& obj, IAllocator& allocator)
static void destroy(KVGroup*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{
@ -85,7 +85,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
UAVCAN_PACKED_END
LinkedListRoot<KVGroup> list_;
IAllocator& allocator_;
IPoolAllocator& allocator_;
KVPair* const static_;
const unsigned num_static_entries_;
@ -101,7 +101,7 @@ class UAVCAN_EXPORT MapBase : Noncopyable
};
protected:
MapBase(KVPair* static_buf, unsigned num_static_entries, IAllocator& allocator)
MapBase(KVPair* static_buf, unsigned num_static_entries, IPoolAllocator& allocator)
: allocator_(allocator)
, static_(static_buf)
, num_static_entries_(num_static_entries)
@ -149,7 +149,7 @@ class UAVCAN_EXPORT Map : public MapBase<Key, Value>
typename MapBase<Key, Value>::KVPair static_[NumStaticEntries];
public:
Map(IAllocator& allocator)
Map(IPoolAllocator& allocator)
: MapBase<Key, Value>(static_, NumStaticEntries, allocator)
{ }
@ -161,7 +161,7 @@ template <typename Key, typename Value>
class UAVCAN_EXPORT Map<Key, Value, 0> : public MapBase<Key, Value>
{
public:
Map(IAllocator& allocator)
Map(IPoolAllocator& allocator)
: MapBase<Key, Value>(NULL, 0, allocator)
{ }

View File

@ -15,7 +15,7 @@ class UAVCAN_EXPORT INode
{
public:
virtual ~INode() { }
virtual IAllocator& getAllocator() = 0;
virtual IPoolAllocator& getAllocator() = 0;
virtual Scheduler& getScheduler() = 0;
virtual const Scheduler& getScheduler() const = 0;
virtual IMarshalBufferProvider& getMarshalBufferProvider() = 0;

View File

@ -122,7 +122,7 @@ class UAVCAN_EXPORT GenericSubscriber : public GenericSubscriberBase
}
public:
TransferForwarder(SelfType& obj, const DataTypeDescriptor& data_type, IAllocator& allocator)
TransferForwarder(SelfType& obj, const DataTypeDescriptor& data_type, IPoolAllocator& allocator)
: TransferListenerType(obj.node_.getDispatcher().getTransferPerfCounter(), data_type, allocator)
, obj_(obj)
{ }
@ -198,7 +198,7 @@ int GenericSubscriber<DataSpec, DataStruct, TransferListenerType>::checkInit()
UAVCAN_TRACE("GenericSubscriber", "Type [%s] is not registered", DataSpec::getDataTypeFullName());
return -ErrUnknownDataType;
}
forwarder_.template construct<SelfType&, const DataTypeDescriptor&, IAllocator&>
forwarder_.template construct<SelfType&, const DataTypeDescriptor&, IPoolAllocator&>
(*this, *descr, node_.getAllocator());
return 0;
}

View File

@ -77,7 +77,7 @@ class UAVCAN_EXPORT Scheduler : Noncopyable
void pollCleanup(MonotonicTime mono_ts, uint32_t num_frames_processed_with_last_spin);
public:
Scheduler(ICanDriver& can_driver, IAllocator& allocator, ISystemClock& sysclock, IOutgoingTransferRegistry& otr)
Scheduler(ICanDriver& can_driver, IPoolAllocator& allocator, ISystemClock& sysclock, IOutgoingTransferRegistry& otr)
: dispatcher_(can_driver, allocator, sysclock, otr)
, prev_cleanup_ts_(sysclock.getMonotonic())
, deadline_resolution_(MonotonicDuration::fromMSec(DefaultDeadlineResolutionMs))

View File

@ -59,7 +59,7 @@ public:
IsDynamicallyAllocatable<Entry>::check();
}
static void destroy(Entry*& obj, IAllocator& allocator);
static void destroy(Entry*& obj, IPoolAllocator& allocator);
bool isExpired(MonotonicTime timestamp) const { return timestamp > deadline; }
@ -87,7 +87,7 @@ private:
};
LinkedListRoot<Entry> queue_;
IAllocator* const allocator_;
IPoolAllocator* const allocator_;
ISystemClock* const sysclock_;
uint32_t rejected_frames_cnt_;
@ -100,7 +100,7 @@ public:
, rejected_frames_cnt_(0)
{ }
CanTxQueue(IAllocator* allocator, ISystemClock* sysclock)
CanTxQueue(IPoolAllocator* allocator, ISystemClock* sysclock)
: allocator_(allocator)
, sysclock_(sysclock)
, rejected_frames_cnt_(0)
@ -160,7 +160,7 @@ class UAVCAN_EXPORT CanIOManager : Noncopyable
int callSelect(CanSelectMasks& inout_masks, MonotonicTime blocking_deadline);
public:
CanIOManager(ICanDriver& driver, IAllocator& allocator, ISystemClock& sysclock)
CanIOManager(ICanDriver& driver, IPoolAllocator& allocator, ISystemClock& sysclock)
: driver_(driver)
, sysclock_(sysclock)
{

View File

@ -102,7 +102,7 @@ class UAVCAN_EXPORT Dispatcher : Noncopyable
void handleLoopbackFrame(const CanRxFrame& can_frame);
public:
Dispatcher(ICanDriver& driver, IAllocator& allocator, ISystemClock& sysclock, IOutgoingTransferRegistry& otr)
Dispatcher(ICanDriver& driver, IPoolAllocator& allocator, ISystemClock& sysclock, IOutgoingTransferRegistry& otr)
: canio_(driver, allocator, sysclock)
, sysclock_(sysclock)
, outgoing_transfer_reg_(otr)

View File

@ -122,7 +122,7 @@ class UAVCAN_EXPORT OutgoingTransferRegistry : public IOutgoingTransferRegistry,
Map<OutgoingTransferRegistryKey, Value, NumStaticEntries> map_;
public:
OutgoingTransferRegistry(IAllocator& allocator)
OutgoingTransferRegistry(IPoolAllocator& allocator)
: map_(allocator)
{ }

View File

@ -107,8 +107,8 @@ class UAVCAN_EXPORT DynamicTransferBufferManagerEntry
enum { Size = MemPoolBlockSize - sizeof(LinkedListNode<Block>) };
uint8_t data[Size];
static Block* instantiate(IAllocator& allocator);
static void destroy(Block*& obj, IAllocator& allocator);
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);
@ -116,7 +116,7 @@ class UAVCAN_EXPORT DynamicTransferBufferManagerEntry
unsigned& total_offset, unsigned& left_to_write);
};
IAllocator& allocator_;
IPoolAllocator& allocator_;
LinkedListRoot<Block> blocks_; // Blocks are ordered from lower to higher buffer offset
uint16_t max_write_pos_;
const uint16_t max_size_;
@ -124,7 +124,7 @@ class UAVCAN_EXPORT DynamicTransferBufferManagerEntry
void resetImpl();
public:
DynamicTransferBufferManagerEntry(IAllocator& allocator, uint16_t max_size)
DynamicTransferBufferManagerEntry(IPoolAllocator& allocator, uint16_t max_size)
: allocator_(allocator)
, max_write_pos_(0)
, max_size_(max_size)
@ -139,8 +139,8 @@ public:
resetImpl();
}
static DynamicTransferBufferManagerEntry* instantiate(IAllocator& allocator, uint16_t max_size);
static void destroy(DynamicTransferBufferManagerEntry*& obj, IAllocator& allocator);
static DynamicTransferBufferManagerEntry* instantiate(IPoolAllocator& allocator, uint16_t max_size);
static void destroy(DynamicTransferBufferManagerEntry*& obj, IPoolAllocator& allocator);
int read(unsigned offset, uint8_t* data, unsigned len) const;
int write(unsigned offset, const uint8_t* data, unsigned len);
@ -258,7 +258,7 @@ public:
class TransferBufferManagerImpl : public ITransferBufferManager, Noncopyable
{
LinkedListRoot<DynamicTransferBufferManagerEntry> dynamic_buffers_;
IAllocator& allocator_;
IPoolAllocator& allocator_;
const uint16_t max_buf_size_;
virtual StaticTransferBufferManagerEntryImpl* getStaticByIndex(uint16_t index) const = 0;
@ -268,7 +268,7 @@ class TransferBufferManagerImpl : public ITransferBufferManager, Noncopyable
void optimizeStorage();
public:
TransferBufferManagerImpl(uint16_t max_buf_size, IAllocator& allocator)
TransferBufferManagerImpl(uint16_t max_buf_size, IPoolAllocator& allocator)
: allocator_(allocator)
, max_buf_size_(max_buf_size)
{ }
@ -295,7 +295,7 @@ class UAVCAN_EXPORT TransferBufferManager : public TransferBufferManagerImpl
}
public:
TransferBufferManager(IAllocator& allocator)
TransferBufferManager(IPoolAllocator& allocator)
: TransferBufferManagerImpl(MaxBufSize, allocator)
{
StaticAssert<(MaxBufSize > 0)>::check();
@ -307,7 +307,7 @@ class UAVCAN_EXPORT TransferBufferManager<0, 0> : public ITransferBufferManager
{
public:
TransferBufferManager() { }
TransferBufferManager(IAllocator&) { }
TransferBufferManager(IPoolAllocator&) { }
ITransferBuffer* access(const TransferBufferManagerKey&) { return NULL; }
ITransferBuffer* create(const TransferBufferManagerKey&) { return NULL; }
void remove(const TransferBufferManagerKey&) { }

View File

@ -145,7 +145,7 @@ class UAVCAN_EXPORT TransferListener : public TransferListenerBase
Map<TransferBufferManagerKey, TransferReceiver, NumStaticReceivers> receivers_;
public:
TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type, IAllocator& allocator)
TransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type, IPoolAllocator& allocator)
: TransferListenerBase(perf, data_type, receivers_, bufmgr_)
, bufmgr_(allocator)
, receivers_(allocator)
@ -200,7 +200,7 @@ private:
public:
ServiceResponseTransferListener(TransferPerfCounter& perf, const DataTypeDescriptor& data_type,
IAllocator& allocator)
IPoolAllocator& allocator)
: BaseType(perf, data_type, allocator)
{ }

View File

@ -30,7 +30,7 @@ std::string CanRxFrame::toString(StringRepresentation mode) const
/*
* CanTxQueue::Entry
*/
void CanTxQueue::Entry::destroy(Entry*& obj, IAllocator& allocator)
void CanTxQueue::Entry::destroy(Entry*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{

View File

@ -24,7 +24,7 @@ std::string TransferBufferManagerKey::toString() const
/*
* DynamicTransferBuffer::Block
*/
DynamicTransferBufferManagerEntry::Block* DynamicTransferBufferManagerEntry::Block::instantiate(IAllocator& allocator)
DynamicTransferBufferManagerEntry::Block* DynamicTransferBufferManagerEntry::Block::instantiate(IPoolAllocator& allocator)
{
void* const praw = allocator.allocate(sizeof(Block));
if (praw == NULL)
@ -34,7 +34,7 @@ DynamicTransferBufferManagerEntry::Block* DynamicTransferBufferManagerEntry::Blo
return new (praw) Block;
}
void DynamicTransferBufferManagerEntry::Block::destroy(Block*& obj, IAllocator& allocator)
void DynamicTransferBufferManagerEntry::Block::destroy(Block*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{
@ -75,7 +75,7 @@ void DynamicTransferBufferManagerEntry::Block::write(const uint8_t*& inptr, unsi
/*
* DynamicTransferBuffer
*/
DynamicTransferBufferManagerEntry* DynamicTransferBufferManagerEntry::instantiate(IAllocator& allocator,
DynamicTransferBufferManagerEntry* DynamicTransferBufferManagerEntry::instantiate(IPoolAllocator& allocator,
uint16_t max_size)
{
void* const praw = allocator.allocate(sizeof(DynamicTransferBufferManagerEntry));
@ -86,7 +86,7 @@ DynamicTransferBufferManagerEntry* DynamicTransferBufferManagerEntry::instantiat
return new (praw) DynamicTransferBufferManagerEntry(allocator, max_size);
}
void DynamicTransferBufferManagerEntry::destroy(DynamicTransferBufferManagerEntry*& obj, IAllocator& allocator)
void DynamicTransferBufferManagerEntry::destroy(DynamicTransferBufferManagerEntry*& obj, IPoolAllocator& allocator)
{
if (obj != NULL)
{

View File

@ -33,4 +33,19 @@ void LimitedPoolAllocator::deallocate(const void* ptr)
}
}
bool LimitedPoolAllocator::isInPool(const void* ptr) const
{
return allocator_.isInPool(ptr);
}
std::size_t LimitedPoolAllocator::getBlockSize() const
{
return allocator_.getBlockSize();
}
std::size_t LimitedPoolAllocator::getNumBlocks() const
{
return allocator_.getNumBlocks();
}
}

View File

@ -120,7 +120,7 @@ class TestListener : public uavcan::TransferListener<MAX_BUF_SIZE, NUM_STATIC_BU
public:
TestListener(uavcan::TransferPerfCounter& perf, const uavcan::DataTypeDescriptor& data_type,
uavcan::IAllocator& allocator)
uavcan::IPoolAllocator& allocator)
: Base(perf, data_type, allocator)
{ }