10#ifndef STK_MEMORY_BLOCKPOOL_H_
11#define STK_MEMORY_BLOCKPOOL_H_
119 explicit BlockMemoryPool(
size_t capacity,
size_t raw_block_size, uint8_t *storage,
120 size_t storage_size,
const char *name =
nullptr);
134#if STK_MEMORY_PLACEMENT_NEW
135 explicit BlockMemoryPool(
size_t capacity,
size_t raw_block_size,
const char *name =
nullptr);
196 template <
typename T> T *
AllocT();
229 bool Free(
void *ptr);
328 size_t storage_size,
const char *name)
350#if STK_SYNC_DEBUG_NAMES
359#if STK_MEMORY_PLACEMENT_NEW
372#if STK_SYNC_DEBUG_NAMES
389#if STK_MEMORY_PLACEMENT_NEW
404 void *block =
nullptr;
409 bool is_timeout =
false;
415 if (!
m_cv.Wait(cs_, timeout_ticks))
441 return static_cast<T *
>(
TimedAlloc(timeout_ticks));
472 bool success =
false;
481 if ((pt < lo) || (pt >= hi))
486 else if ((
static_cast<size_t>(pt - lo) %
m_block_size) != 0U)
500 #if defined(_DEBUG) || defined(DEBUG)
501 bool is_double_free =
false;
507 if (node ==
reinterpret_cast<const MemoryBlock *
>(ptr))
510 is_double_free =
true;
519 auto *
const blk =
reinterpret_cast<MemoryBlock *
>(ptr);
Weak declaration of memory allocator: stk::memory::MemoryAllocator.
#define STK_UNUSED(X)
Explicitly marks a variable as unused to suppress compiler warnings.
#define STK_ASSERT(e)
Runtime assertion. Halts execution if the expression e evaluates to false.
#define STK_VIRT_DTOR
Makes destructors virtual and compliant to strict rules if STK_STRICT_COMPLIANCY=0.
Implementation of synchronization primitive: stk::sync::ConditionVariable.
Namespace of STK package.
uintptr_t Word
Native processor word type.
constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
int32_t Timeout
Timeout time (ticks).
static constexpr T Max(T a, T b)
Compile-time maximum of two values.
constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
Memory-related primitives.
static constexpr T * WordToPtr(Word value) noexcept
Cast a CPU register-width integer back to a pointer.
static constexpr Word PtrToWord(T *const ptr) noexcept
Cast a pointer to a CPU register-width integer.
bool IsInsideISR()
Check whether the CPU is currently executing inside a hardware interrupt service routine (ISR).
Memory allocator for allocating dynamic memory.
static void FreeArrayT(TElement ptr[], size_t count)
Destroy and free an array allocated via AllocateT().
size_t GetUsedCount() const
Get the number of currently allocated (outstanding) blocks.
static const uint32_t BLOCK_ALIGN
Minimum block alignment in bytes: sizeof(MemoryBlock).
size_t GetFreeCount() const
Get the number of free (available) blocks.
uint8_t * m_storage
flat byte array holding all N blocks (owned or external)
void * PopFreeList()
Pop the head block from the free-list, increment m_used_count, and return it.
static const size_t CAPACITY_MAX
Max capacity supported (number of blocks).
size_t m_capacity
total number of blocks
size_t GetCapacity() const
Get the total block capacity of the pool.
STK_NONCOPYABLE_CLASS(BlockMemoryPool)
T * TryAllocT()
Non-blocking typed allocation attempt.
bool IsFull() const
Check whether all blocks are currently allocated (pool exhausted).
bool IsStorageValid() const
Verify that the backing storage is valid and the pool is ready for use.
BlockMemoryPool(size_t capacity, size_t raw_block_size, uint8_t *storage, size_t storage_size, const char *name=nullptr)
Construct a pool backed by caller-supplied (external) storage.
bool Free(void *ptr)
Return a previously allocated block to the pool.
STK_VIRT_DTOR ~BlockMemoryPool()
Destructor.
void BuildFreeList()
Initialise the intrusive free-list across m_storage.
void * TryAlloc()
Non-blocking allocation attempt.
static constexpr size_t AlignBlockSize(size_t raw_size)
Round a raw block size up to the nearest multiple of BLOCK_ALIGN.
MemoryBlock * m_free_list
head of the intrusive free-list (nullptr when pool is empty)
void * TimedAlloc(Timeout timeout_ticks=WAIT_INFINITE)
Allocate one block, blocking until one becomes available or the timeout expires.
sync::ConditionVariable m_cv
signalled by Free() to wake one task blocked in TimedAlloc()
size_t GetBlockSize() const
Get the aligned block size used internally by the allocator.
void * Alloc()
Allocate one block, blocking indefinitely until one is available.
T * TimedAllocT(Timeout timeout_ticks=WAIT_INFINITE)
Allocate one typed block, blocking until one becomes available or the timeout expires.
bool IsEmpty() const
Check whether all blocks are free (no outstanding allocations).
size_t m_used_count
number of blocks currently allocated (outstanding)
T * AllocT()
Allocate one typed block, blocking indefinitely until one is available.
size_t m_block_size
aligned block size in bytes (>= BLOCK_ALIGN)
bool m_storage_owned
true -> storage is heap-allocated; free in destructor
Intrusive free-list node overlaid on the first word of every free block.
MemoryBlock * next
next free block in the list, or nullptr if this is the last one
void SetTraceName(const char *name)
Set name.
RAII-style low-level synchronization primitive for atomic code execution. Used as building brick for ...
Condition Variable primitive for signaling between tasks based on specific predicates.