mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-24 16:53:33 +08:00
Simplified Multiset<>
This commit is contained in:
@@ -24,11 +24,12 @@ namespace uavcan
|
|||||||
* they don't have to be copyable.
|
* 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.
|
* 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 <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
class UAVCAN_EXPORT MultisetBase : Noncopyable
|
class UAVCAN_EXPORT Multiset : Noncopyable
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
struct Item : ::uavcan::Noncopyable
|
struct Item : ::uavcan::Noncopyable
|
||||||
{
|
{
|
||||||
T* ptr;
|
T* ptr;
|
||||||
@@ -116,13 +117,16 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Data
|
||||||
|
*/
|
||||||
LinkedListRoot<Chunk> list_;
|
LinkedListRoot<Chunk> list_;
|
||||||
IPoolAllocator& allocator_;
|
IPoolAllocator& allocator_;
|
||||||
#if !UAVCAN_TINY
|
Item static_[NumStaticEntries];
|
||||||
Item* const static_;
|
|
||||||
const unsigned num_static_entries_;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methods
|
||||||
|
*/
|
||||||
Item* findOrCreateFreeSlot();
|
Item* findOrCreateFreeSlot();
|
||||||
|
|
||||||
void compact();
|
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:
|
public:
|
||||||
|
Multiset(IPoolAllocator& allocator)
|
||||||
|
: allocator_(allocator)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
~Multiset()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates one item in-place and returns a pointer to it.
|
* Creates one item in-place and returns a pointer to it.
|
||||||
* If creation fails due to lack of memory, NULL will be returned.
|
* If creation fails due to lack of memory, NULL will be returned.
|
||||||
@@ -292,7 +284,7 @@ public:
|
|||||||
template <typename Predicate>
|
template <typename Predicate>
|
||||||
const T* find(Predicate predicate) const
|
const T* find(Predicate predicate) const
|
||||||
{
|
{
|
||||||
return const_cast<MultisetBase<T>*>(this)->find<Predicate>(predicate);
|
return const_cast<Multiset*>(this)->find<Predicate>(predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -329,7 +321,7 @@ public:
|
|||||||
|
|
||||||
const T* getByIndex(unsigned index) const
|
const T* getByIndex(unsigned index) const
|
||||||
{
|
{
|
||||||
return const_cast<MultisetBase<T>*>(this)->getByIndex(index);
|
return const_cast<Multiset*>(this)->getByIndex(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -350,53 +342,17 @@ public:
|
|||||||
unsigned getNumDynamicItems() const;
|
unsigned getNumDynamicItems() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T, unsigned NumStaticEntries = 0>
|
|
||||||
class UAVCAN_EXPORT Multiset : public MultisetBase<T>
|
|
||||||
{
|
|
||||||
typename MultisetBase<T>::Item static_[NumStaticEntries];
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
#if !UAVCAN_TINY
|
|
||||||
|
|
||||||
// This instantiation will not be valid in UAVCAN_TINY mode
|
|
||||||
explicit Multiset(IPoolAllocator& allocator)
|
|
||||||
: MultisetBase<T>(static_, NumStaticEntries, allocator)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~Multiset() { this->clear(); }
|
|
||||||
|
|
||||||
#endif // !UAVCAN_TINY
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class UAVCAN_EXPORT Multiset<T, 0> : public MultisetBase<T>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit Multiset(IPoolAllocator& allocator)
|
|
||||||
#if UAVCAN_TINY
|
|
||||||
: MultisetBase<T>(allocator)
|
|
||||||
#else
|
|
||||||
: MultisetBase<T>(NULL, 0, allocator)
|
|
||||||
#endif
|
|
||||||
{ }
|
|
||||||
|
|
||||||
~Multiset() { this->clear(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MultisetBase<>
|
* Multiset<>
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
typename MultisetBase<T>::Item* MultisetBase<T>::findOrCreateFreeSlot()
|
typename Multiset<T, NumStaticEntries>::Item* Multiset<T, NumStaticEntries>::findOrCreateFreeSlot()
|
||||||
{
|
{
|
||||||
#if !UAVCAN_TINY
|
#if !UAVCAN_TINY
|
||||||
// Search in static pool
|
// Search in static pool
|
||||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
for (unsigned i = 0; i < NumStaticEntries; i++)
|
||||||
{
|
{
|
||||||
if (!static_[i].isConstructed())
|
if (!static_[i].isConstructed())
|
||||||
{
|
{
|
||||||
@@ -429,8 +385,8 @@ typename MultisetBase<T>::Item* MultisetBase<T>::findOrCreateFreeSlot()
|
|||||||
return &chunk->items[0];
|
return &chunk->items[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
void MultisetBase<T>::compact()
|
void Multiset<T, NumStaticEntries>::compact()
|
||||||
{
|
{
|
||||||
Chunk* p = list_.get();
|
Chunk* p = list_.get();
|
||||||
while (p)
|
while (p)
|
||||||
@@ -454,14 +410,14 @@ void MultisetBase<T>::compact()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
template <typename Predicate>
|
template <typename Predicate>
|
||||||
void MultisetBase<T>::removeWhere(Predicate predicate, const RemoveStrategy strategy)
|
void Multiset<T, NumStaticEntries>::removeWhere(Predicate predicate, const RemoveStrategy strategy)
|
||||||
{
|
{
|
||||||
unsigned num_removed = 0;
|
unsigned num_removed = 0;
|
||||||
|
|
||||||
#if !UAVCAN_TINY
|
#if !UAVCAN_TINY
|
||||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
for (unsigned i = 0; i < NumStaticEntries; i++)
|
||||||
{
|
{
|
||||||
if (static_[i].isConstructed())
|
if (static_[i].isConstructed())
|
||||||
{
|
{
|
||||||
@@ -512,12 +468,12 @@ void MultisetBase<T>::removeWhere(Predicate predicate, const RemoveStrategy stra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
template <typename Predicate>
|
template <typename Predicate>
|
||||||
T* MultisetBase<T>::find(Predicate predicate)
|
T* Multiset<T, NumStaticEntries>::find(Predicate predicate)
|
||||||
{
|
{
|
||||||
#if !UAVCAN_TINY
|
#if !UAVCAN_TINY
|
||||||
for (unsigned i = 0; i < num_static_entries_; i++)
|
for (unsigned i = 0; i < NumStaticEntries; i++)
|
||||||
{
|
{
|
||||||
if (static_[i].isConstructed())
|
if (static_[i].isConstructed())
|
||||||
{
|
{
|
||||||
@@ -547,12 +503,12 @@ T* MultisetBase<T>::find(Predicate predicate)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
unsigned MultisetBase<T>::getNumStaticItems() const
|
unsigned Multiset<T, NumStaticEntries>::getNumStaticItems() const
|
||||||
{
|
{
|
||||||
unsigned num = 0;
|
unsigned num = 0;
|
||||||
#if !UAVCAN_TINY
|
#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;
|
num += static_[i].isConstructed() ? 1U : 0U;
|
||||||
}
|
}
|
||||||
@@ -560,8 +516,8 @@ unsigned MultisetBase<T>::getNumStaticItems() const
|
|||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T, unsigned NumStaticEntries>
|
||||||
unsigned MultisetBase<T>::getNumDynamicItems() const
|
unsigned Multiset<T, NumStaticEntries>::getNumDynamicItems() const
|
||||||
{
|
{
|
||||||
unsigned num = 0;
|
unsigned num = 0;
|
||||||
Chunk* p = list_.get();
|
Chunk* p = list_.get();
|
||||||
|
|||||||
@@ -214,40 +214,6 @@ TEST(Multiset, Basic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TEST(Multiset, NoStatic)
|
|
||||||
{
|
|
||||||
using uavcan::Multiset;
|
|
||||||
|
|
||||||
static const int POOL_BLOCKS = 3;
|
|
||||||
uavcan::PoolAllocator<uavcan::MemPoolBlockSize * POOL_BLOCKS, uavcan::MemPoolBlockSize> pool;
|
|
||||||
uavcan::PoolManager<2> poolmgr;
|
|
||||||
poolmgr.addPool(&pool);
|
|
||||||
|
|
||||||
typedef Multiset<std::string> MultisetType;
|
|
||||||
std::auto_ptr<MultisetType> 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)
|
TEST(Multiset, PrimitiveKey)
|
||||||
{
|
{
|
||||||
using uavcan::Multiset;
|
using uavcan::Multiset;
|
||||||
|
|||||||
Reference in New Issue
Block a user