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);
218 template <
typename T> T *
AllocT();
254 bool Free(
void *ptr);
353 size_t storage_size,
const char *name)
375#if STK_SYNC_DEBUG_NAMES
384#if STK_MEMORY_PLACEMENT_NEW
397#if STK_SYNC_DEBUG_NAMES
414#if STK_MEMORY_PLACEMENT_NEW
433 if (block ==
nullptr)
454 const Ticks deadline = (timed_wait ? (
GetTicks() +
static_cast<Ticks>(timeout_ticks)) : 0);
461 Timeout remaining = timeout_ticks;
470 result =
m_cv.WaitEx(cs_, remaining);
496 void *block =
nullptr;
511 return static_cast<T *
>(
TimedAlloc(timeout_ticks));
542 bool success =
false;
551 if ((pt < lo) || (pt >= hi))
556 else if ((
static_cast<size_t>(pt - lo) %
m_block_size) != 0U)
570 #if defined(_DEBUG) || defined(DEBUG)
571 bool is_double_free =
false;
577 if (node ==
reinterpret_cast<const MemoryBlock *
>(ptr))
580 is_double_free =
true;
589 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.
static constexpr Timeout NO_WAIT
Timeout value: return immediately if the synchronization object is not yet signaled (non-blocking pol...
EWaitResult
Wait result (see IKernelService::Wait).
@ WAIT_RESULT_FAIL
IKernelService::Wait returned with error without waiting.
@ WAIT_RESULT_TIMEOUT
The wake was caused by a timeout expiry.
@ WAIT_RESULT_SIGNAL
The wake was caused by a signal.
int64_t Ticks
Ticks value.
int32_t Timeout
Timeout time (ticks).
static constexpr T Max(T a, T b) noexcept
Compile-time maximum of two values.
static Ticks GetTicks()
Get number of ticks elapsed since kernel start.
static constexpr Timeout WAIT_INFINITE
Timeout value: block indefinitely until the synchronization object is signaled.
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-related primitives.
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 size_t BLOCK_ALIGN
Minimum block alignment in bytes: sizeof(MemoryBlock).
EWaitResult TimedAllocEx(void **block, Timeout timeout_ticks=WAIT_INFINITE)
Allocate one block, preserving the full wait outcome.
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.