diff --git a/libuavcan/include/uavcan/dynamic_memory.hpp b/libuavcan/include/uavcan/dynamic_memory.hpp index 0c6945abca..d130b8ccb7 100644 --- a/libuavcan/include/uavcan/dynamic_memory.hpp +++ b/libuavcan/include/uavcan/dynamic_memory.hpp @@ -97,6 +97,26 @@ public: int getNumUsedBlocks() const { return NumBlocks - getNumFreeBlocks(); } }; + +class LimitedPoolAllocator : public IAllocator +{ + IAllocator& allocator_; + const std::size_t max_blocks_; + std::size_t used_blocks_; + +public: + LimitedPoolAllocator(IAllocator& allocator, std::size_t max_blocks) + : allocator_(allocator) + , max_blocks_(max_blocks) + , used_blocks_(0) + { + assert(max_blocks_ > 0); + } + + void* allocate(std::size_t size); + void deallocate(const void* ptr); +}; + // ---------------------------------------------------------------------------- /* diff --git a/libuavcan/src/uc_dynamic_memory.cpp b/libuavcan/src/uc_dynamic_memory.cpp new file mode 100644 index 0000000000..31dd40e078 --- /dev/null +++ b/libuavcan/src/uc_dynamic_memory.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include + +namespace uavcan +{ +/* + * LimitedPoolAllocator + */ +void* LimitedPoolAllocator::allocate(std::size_t size) +{ + if (used_blocks_ < max_blocks_) + { + used_blocks_++; + return allocator_.allocate(size); + } + else + { + return NULL; + } +} + +void LimitedPoolAllocator::deallocate(const void* ptr) +{ + allocator_.deallocate(ptr); + + assert(used_blocks_ > 0); + if (used_blocks_ > 0) + { + used_blocks_--; + } +} + +} diff --git a/libuavcan/test/dynamic_memory.cpp b/libuavcan/test/dynamic_memory.cpp index 7ebc43c4dc..24662b0988 100644 --- a/libuavcan/test/dynamic_memory.cpp +++ b/libuavcan/test/dynamic_memory.cpp @@ -92,3 +92,27 @@ TEST(DynamicMemory, OutOfMemory) EXPECT_EQ(1, pool32.getNumUsedBlocks()); EXPECT_EQ(1, pool64.getNumUsedBlocks()); // Make sure it was properly deallocated } + +TEST(DynamicMemory, LimitedPoolAllocator) +{ + uavcan::PoolAllocator<128, 32> pool32; + uavcan::LimitedPoolAllocator lim(pool32, 2); + + const void* ptr1 = lim.allocate(1); + const void* ptr2 = lim.allocate(1); + const void* ptr3 = lim.allocate(1); + + EXPECT_TRUE(ptr1); + EXPECT_TRUE(ptr2); + EXPECT_FALSE(ptr3); + + lim.deallocate(ptr2); + const void* ptr4 = lim.allocate(1); + lim.deallocate(ptr1); + const void* ptr5 = lim.allocate(1); + const void* ptr6 = lim.allocate(1); + + EXPECT_TRUE(ptr4); + EXPECT_TRUE(ptr5); + EXPECT_FALSE(ptr6); +}