mirror of
https://github.com/ETLCPP/etl.git
synced 2026-11-09 14:49:53 +08:00
Modified factory to use pool instead of custom internal allocator.
This commit is contained in:
parent
5752151b54
commit
1d6058ffac
221
src/factory.h
221
src/factory.h
@ -39,6 +39,7 @@ SOFTWARE.
|
||||
#include "alignment.h"
|
||||
#include "static_assert.h"
|
||||
#include "type_lookup.h"
|
||||
#include <pool.h>
|
||||
|
||||
#undef ETL_FILE
|
||||
#define ETL_FILE "40"
|
||||
@ -125,12 +126,9 @@ namespace etl
|
||||
static const size_t MAX_SIZE = MAX_SIZE_;
|
||||
|
||||
//*************************************************************************
|
||||
/// Constructor
|
||||
/// Default constructor.
|
||||
//*************************************************************************
|
||||
factory()
|
||||
: p_next(reinterpret_cast<char*>(&buffer[0])),
|
||||
items_allocated(0),
|
||||
items_initialised(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -142,11 +140,20 @@ namespace etl
|
||||
{
|
||||
STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
|
||||
|
||||
T* p = reinterpret_cast<T*>(allocate_item());
|
||||
T* p = nullptr;
|
||||
|
||||
if (p != nullptr)
|
||||
if (pool.full())
|
||||
{
|
||||
new (p) T();
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pool.allocate<T>();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
new (p) T();
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -160,11 +167,20 @@ namespace etl
|
||||
{
|
||||
STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
|
||||
|
||||
T* p = reinterpret_cast<T*>(allocate_item());
|
||||
T* p = nullptr;
|
||||
|
||||
if (p != nullptr)
|
||||
if (pool.full())
|
||||
{
|
||||
new (p) T(p1);
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pool.allocate<T>();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
new (p) T(p1);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -178,11 +194,20 @@ namespace etl
|
||||
{
|
||||
STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
|
||||
|
||||
T* p = reinterpret_cast<T*>(allocate_item());
|
||||
T* p = nullptr;
|
||||
|
||||
if (p != nullptr)
|
||||
if (pool.full())
|
||||
{
|
||||
new (p) T(p1, p2);
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pool.allocate<T>();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
new (p) T(p1, p2);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -196,11 +221,20 @@ namespace etl
|
||||
{
|
||||
STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
|
||||
|
||||
T* p = reinterpret_cast<T*>(allocate_item());
|
||||
T* p = nullptr;
|
||||
|
||||
if (p != nullptr)
|
||||
if (pool.full())
|
||||
{
|
||||
new (p) T(p1, p2, p3);
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pool.allocate<T>();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
new (p) T(p1, p2, p3);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -214,11 +248,20 @@ namespace etl
|
||||
{
|
||||
STATIC_ASSERT((etl::is_one_of<T, TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::value), "Unsupported type");
|
||||
|
||||
T* p = reinterpret_cast<T*>(allocate_item());
|
||||
T* p = nullptr;
|
||||
|
||||
if (p != nullptr)
|
||||
if (pool.full())
|
||||
{
|
||||
new (p) T(p1, p2, p3, p4);
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pool.allocate<T>();
|
||||
|
||||
if (p != nullptr)
|
||||
{
|
||||
new (p) T(p1, p2, p3, p4);
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
@ -305,7 +348,18 @@ namespace etl
|
||||
|
||||
p->~T();
|
||||
|
||||
return release_item(reinterpret_cast<char*>(const_cast<T*>(p)));
|
||||
void* vp = reinterpret_cast<char*>(const_cast<T*>(p));
|
||||
|
||||
if (pool.is_in_pool(vp))
|
||||
{
|
||||
pool.release(reinterpret_cast<char*>(const_cast<T*>(p)));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(factory_did_not_create));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -321,7 +375,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
size_t available() const
|
||||
{
|
||||
return MAX_SIZE - items_allocated;
|
||||
return pool.available();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -329,7 +383,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
size_t size() const
|
||||
{
|
||||
return items_allocated;
|
||||
return pool.size();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -338,7 +392,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
bool empty() const
|
||||
{
|
||||
return items_allocated == 0;
|
||||
return pool.empty();
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
@ -347,7 +401,7 @@ namespace etl
|
||||
//*************************************************************************
|
||||
bool full() const
|
||||
{
|
||||
return items_allocated == MAX_SIZE;;
|
||||
return pool.full();
|
||||
}
|
||||
|
||||
private:
|
||||
@ -355,121 +409,10 @@ namespace etl
|
||||
factory(const factory&);
|
||||
factory& operator =(const factory&);
|
||||
|
||||
//*************************************************************************
|
||||
/// Allocate an item from the pool.
|
||||
//*************************************************************************
|
||||
char* allocate_item()
|
||||
{
|
||||
char* p_value = nullptr;
|
||||
|
||||
// Any free space left?
|
||||
if (items_allocated < MAX_SIZE)
|
||||
{
|
||||
// Initialise another one if necessary.
|
||||
if (items_initialised < MAX_SIZE)
|
||||
{
|
||||
uintptr_t p = reinterpret_cast<uintptr_t>(reinterpret_cast<char*>(&buffer[0]) + (items_initialised * ITEM_SIZE));
|
||||
*reinterpret_cast<uintptr_t*>(p) = p + ITEM_SIZE;
|
||||
++items_initialised;
|
||||
}
|
||||
|
||||
// Get the address of new allocated item.
|
||||
p_value = p_next;
|
||||
|
||||
++items_allocated;
|
||||
if (items_allocated != MAX_SIZE)
|
||||
{
|
||||
// Set up the pointer to the next free item
|
||||
p_next = *reinterpret_cast<char**>(p_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more left!
|
||||
p_next = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(etl::factory_cannot_create));
|
||||
}
|
||||
|
||||
return p_value;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Release an item back to the pool.
|
||||
//*************************************************************************
|
||||
bool release_item(char* p_value)
|
||||
{
|
||||
if (is_item_in_pool(p_value))
|
||||
{
|
||||
if (p_next != nullptr)
|
||||
{
|
||||
// Point it to the current free item.
|
||||
*(uintptr_t*)p_value = reinterpret_cast<uintptr_t>(p_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the only free item.
|
||||
*((uintptr_t*)p_value) = 0;
|
||||
}
|
||||
|
||||
p_next = p_value;
|
||||
|
||||
--items_allocated;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ETL_ASSERT(false, ETL_ERROR(factory_did_not_create));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
/// Check if the item belongs to this pool.
|
||||
//*************************************************************************
|
||||
bool is_item_in_pool(char* p) const
|
||||
{
|
||||
if (empty() || (p == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Within the range of the buffer?
|
||||
intptr_t distance = p - reinterpret_cast<const char*>(&buffer[0]);
|
||||
bool is_within_range = (distance >= 0) && (distance <= intptr_t((ITEM_SIZE * MAX_SIZE) - ITEM_SIZE));
|
||||
|
||||
// Modulus and division can be slow on some architectures, so only do this in debug.
|
||||
#if defined(ETL_DEBUG)
|
||||
// Is the address on a valid object boundary?
|
||||
bool is_valid_address = ((distance % ITEM_SIZE) == 0);
|
||||
#else
|
||||
bool is_valid_address = true;
|
||||
#endif
|
||||
|
||||
return is_within_range && is_valid_address;
|
||||
}
|
||||
|
||||
// The pool element.
|
||||
union Element
|
||||
{
|
||||
uintptr_t next; ///< Pointer to the next free element.
|
||||
char value[etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::size]; ///< Storage for value type.
|
||||
typename etl::type_with_alignment<etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::alignment>::type dummy; ///< Dummy item to get correct alignment.
|
||||
};
|
||||
|
||||
///< The memory for the pool of objects.
|
||||
typename etl::aligned_storage<sizeof(Element), etl::alignment_of<Element>::value>::type buffer[MAX_SIZE];
|
||||
|
||||
static const uint32_t ITEM_SIZE = sizeof(Element);
|
||||
|
||||
char* p_next;
|
||||
|
||||
uint32_t items_allocated; ///< The number of items allocated.
|
||||
uint32_t items_initialised; ///< The number of items initialised.
|
||||
// The pool.
|
||||
etl::generic_pool<etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::size,
|
||||
etl::largest<TT1, TT2, TT3, TT4, TT5, TT6, TT7, TT8, TT9, TT10, TT11, TT12, TT13, TT14, TT15, TT16>::alignment,
|
||||
MAX_SIZE> pool;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user