diff --git a/libuavcan/include/uavcan/util/multiset.hpp b/libuavcan/include/uavcan/util/multiset.hpp index d796b1bff6..aae7d295f4 100644 --- a/libuavcan/include/uavcan/util/multiset.hpp +++ b/libuavcan/include/uavcan/util/multiset.hpp @@ -24,11 +24,12 @@ namespace uavcan * they don't have to be copyable. * * Items can be allocated in a static buffer or in the node's memory pool if the static buffer is exhausted. + * + * Number of static entries must not be less than 1. */ -template -class UAVCAN_EXPORT MultisetBase : Noncopyable +template +class UAVCAN_EXPORT Multiset : Noncopyable { -protected: struct Item : ::uavcan::Noncopyable { T* ptr; @@ -116,13 +117,16 @@ private: } }; + /* + * Data + */ LinkedListRoot list_; IPoolAllocator& allocator_; -#if !UAVCAN_TINY - Item* const static_; - const unsigned num_static_entries_; -#endif + Item static_[NumStaticEntries]; + /* + * Methods + */ Item* findOrCreateFreeSlot(); void compact(); @@ -186,28 +190,16 @@ private: } }; -protected: -#if UAVCAN_TINY - MultisetBase(IPoolAllocator& allocator) - : allocator_(allocator) - { - UAVCAN_ASSERT(Item() == Item()); - } -#else - MultisetBase(Item* static_buf, unsigned num_static_entries, IPoolAllocator& allocator) - : allocator_(allocator) - , static_(static_buf) - , num_static_entries_(num_static_entries) - { } -#endif - - /// Derived class destructor must call clear(); - ~MultisetBase() - { - UAVCAN_ASSERT(getSize() == 0); - } - public: + Multiset(IPoolAllocator& allocator) + : allocator_(allocator) + { } + + ~Multiset() + { + clear(); + } + /** * Creates one item in-place and returns a pointer to it. * If creation fails due to lack of memory, NULL will be returned. @@ -292,7 +284,7 @@ public: template const T* find(Predicate predicate) const { - return const_cast*>(this)->find(predicate); + return const_cast(this)->find(predicate); } /** @@ -329,7 +321,7 @@ public: const T* getByIndex(unsigned index) const { - return const_cast*>(this)->getByIndex(index); + return const_cast(this)->getByIndex(index); } /** @@ -350,53 +342,17 @@ public: unsigned getNumDynamicItems() const; }; - -template -class UAVCAN_EXPORT Multiset : public MultisetBase -{ - typename MultisetBase::Item static_[NumStaticEntries]; - -public: - -#if !UAVCAN_TINY - - // This instantiation will not be valid in UAVCAN_TINY mode - explicit Multiset(IPoolAllocator& allocator) - : MultisetBase(static_, NumStaticEntries, allocator) - { } - - ~Multiset() { this->clear(); } - -#endif // !UAVCAN_TINY -}; - - -template -class UAVCAN_EXPORT Multiset : public MultisetBase -{ -public: - explicit Multiset(IPoolAllocator& allocator) -#if UAVCAN_TINY - : MultisetBase(allocator) -#else - : MultisetBase(NULL, 0, allocator) -#endif - { } - - ~Multiset() { this->clear(); } -}; - // ---------------------------------------------------------------------------- /* - * MultisetBase<> + * Multiset<> */ -template -typename MultisetBase::Item* MultisetBase::findOrCreateFreeSlot() +template +typename Multiset::Item* Multiset::findOrCreateFreeSlot() { #if !UAVCAN_TINY // Search in static pool - for (unsigned i = 0; i < num_static_entries_; i++) + for (unsigned i = 0; i < NumStaticEntries; i++) { if (!static_[i].isConstructed()) { @@ -429,8 +385,8 @@ typename MultisetBase::Item* MultisetBase::findOrCreateFreeSlot() return &chunk->items[0]; } -template -void MultisetBase::compact() +template +void Multiset::compact() { Chunk* p = list_.get(); while (p) @@ -454,14 +410,14 @@ void MultisetBase::compact() } } -template +template template -void MultisetBase::removeWhere(Predicate predicate, const RemoveStrategy strategy) +void Multiset::removeWhere(Predicate predicate, const RemoveStrategy strategy) { unsigned num_removed = 0; #if !UAVCAN_TINY - for (unsigned i = 0; i < num_static_entries_; i++) + for (unsigned i = 0; i < NumStaticEntries; i++) { if (static_[i].isConstructed()) { @@ -512,12 +468,12 @@ void MultisetBase::removeWhere(Predicate predicate, const RemoveStrategy stra } } -template +template template -T* MultisetBase::find(Predicate predicate) +T* Multiset::find(Predicate predicate) { #if !UAVCAN_TINY - for (unsigned i = 0; i < num_static_entries_; i++) + for (unsigned i = 0; i < NumStaticEntries; i++) { if (static_[i].isConstructed()) { @@ -547,12 +503,12 @@ T* MultisetBase::find(Predicate predicate) return NULL; } -template -unsigned MultisetBase::getNumStaticItems() const +template +unsigned Multiset::getNumStaticItems() const { unsigned num = 0; #if !UAVCAN_TINY - for (unsigned i = 0; i < num_static_entries_; i++) + for (unsigned i = 0; i < NumStaticEntries; i++) { num += static_[i].isConstructed() ? 1U : 0U; } @@ -560,8 +516,8 @@ unsigned MultisetBase::getNumStaticItems() const return num; } -template -unsigned MultisetBase::getNumDynamicItems() const +template +unsigned Multiset::getNumDynamicItems() const { unsigned num = 0; Chunk* p = list_.get(); diff --git a/libuavcan/test/util/multiset.cpp b/libuavcan/test/util/multiset.cpp index 35e7376e75..8ff43e69b9 100644 --- a/libuavcan/test/util/multiset.cpp +++ b/libuavcan/test/util/multiset.cpp @@ -214,40 +214,6 @@ TEST(Multiset, Basic) } -TEST(Multiset, NoStatic) -{ - using uavcan::Multiset; - - static const int POOL_BLOCKS = 3; - uavcan::PoolAllocator pool; - uavcan::PoolManager<2> poolmgr; - poolmgr.addPool(&pool); - - typedef Multiset MultisetType; - std::auto_ptr mset(new MultisetType(poolmgr)); - - // Empty - mset->removeFirst("foo"); - ASSERT_EQ(0, pool.getNumUsedBlocks()); - ASSERT_FALSE(mset->getByIndex(0)); - - // Insertion - ASSERT_EQ("a", *mset->emplace("a")); - ASSERT_EQ("b", *mset->emplace("b")); - ASSERT_LE(1, pool.getNumUsedBlocks()); - ASSERT_EQ(0, mset->getNumStaticItems()); - ASSERT_EQ(2, mset->getNumDynamicItems()); - -#if UAVCAN_CPP_VERSION >= UAVCAN_CPP11 - // Only C++11 because C++03 uses one entry per pool block which breaks ordering - ASSERT_EQ("a", *mset->getByIndex(0)); - ASSERT_EQ("b", *mset->getByIndex(1)); - ASSERT_FALSE(mset->getByIndex(3)); - ASSERT_FALSE(mset->getByIndex(1000)); -#endif -} - - TEST(Multiset, PrimitiveKey) { using uavcan::Multiset;