API Reference for eAlloc
-
struct BlockHeader
- #include <tlsf.hpp>
Header for memory blocks in the TLSF allocator.
This structure stores meta-information about a memory block used by the TLSF (Two-Level Segregated Fit) allocator. It includes a pointer to the previous physical block, the block’s size and allocation flags, and pointers to the next and previous free blocks in the free list.
Public Members
-
struct BlockHeader *prev_phys_block
-
size_t size_and_flags
-
struct BlockHeader *next_free
-
struct BlockHeader *prev_free
-
struct BlockHeader *prev_phys_block
-
struct Control
- #include <tlsf.hpp>
Control structure for the TLSF allocator.
This structure maintains the overall state of the allocator, including:
A special block (block_null) used to indicate empty free lists.
A bitmap (fl_bitmap) representing the first-level free block availability.
An array (cabinets) of second-level indices that manage the free lists for specific size ranges.
Public Members
-
BlockHeader block_null
-
uint32_t fl_bitmap = 0
-
SecondLevel cabinets[FL_INDEX_COUNT]
-
class eAlloc
- #include <eAlloc.hpp>
A memory allocator class based on the Two-Level Segregated Fit (TLSF) algorithm.
The eAlloc class provides efficient memory management with support for multiple pools, alignment, reallocation, and storage reporting.
Public Types
Public Functions
-
explicit eAlloc(void *mem, size_t bytes)
Constructs an eAlloc instance with an initial memory pool.
- Parameters:
mem – Pointer to the initial memory block.
bytes – Size of the initial memory block in bytes.
-
void *malloc(size_t size)
Allocates a block of memory of the specified size.
- Parameters:
size – The size of the memory block to allocate in bytes.
- Returns:
Pointer to the allocated memory, or nullptr if allocation fails.
-
void free(void *ptr)
Frees a previously allocated memory block.
- Parameters:
ptr – Pointer to the memory block to free.
-
void *memalign(size_t align, size_t size)
Allocates a memory block with specified alignment and size.
- Parameters:
align – The alignment requirement in bytes (must be a power of 2).
size – The size of the memory block to allocate in bytes.
- Returns:
Pointer to the allocated memory, or nullptr if allocation fails.
-
void *realloc(void *ptr, size_t size)
Reallocates a memory block to a new size.
- Parameters:
ptr – Pointer to the memory block to reallocate.
size – The new size of the memory block in bytes.
- Returns:
Pointer to the reallocated memory, or nullptr if reallocation fails.
-
void *calloc(size_t num, size_t size)
Allocates memory for an array and initializes it to zero.
- Parameters:
num – Number of elements in the array.
size – Size of each element in bytes.
- Returns:
Pointer to the allocated memory, or nullptr if allocation fails.
-
template<typename T>
inline T *allocate(const T &obj) Allocates memory for an object and constructs it by copying.
- Template Parameters:
T – The type of the object to allocate.
- Parameters:
obj – The object to copy-construct.
- Returns:
Pointer to the constructed object, or nullptr if allocation fails.
-
template<typename T, typename ...Args>
inline T *allocate(Args&&... args) Allocates memory for an object and constructs it with arguments.
- Template Parameters:
T – The type of the object to allocate.
Args – Types of the constructor arguments.
- Parameters:
args – Arguments to pass to the object’s constructor.
- Returns:
Pointer to the constructed object, or nullptr if allocation fails.
-
template<typename T>
inline void deallocate(T *obj) Deallocates an object and destroys it.
- Template Parameters:
T – The type of the object to deallocate.
- Parameters:
obj – Pointer to the object to deallocate.
-
void *add_pool(void *mem, size_t bytes)
Adds a new memory pool to the allocator.
- Parameters:
mem – Pointer to the memory block to add as a pool.
bytes – Size of the memory block in bytes.
- Returns:
Pointer to the added pool, or nullptr if addition fails.
-
void remove_pool(void *pool)
Removes a memory pool from the allocator.
Note
The pool must contain no allocated blocks; all memory allocated from it must be freed prior to removal, or undefined behavior will result.
- Parameters:
pool – Pointer to the pool to remove.
-
int check_pool(void *pool)
Checks the integrity of a specific memory pool.
- Parameters:
pool – Pointer to the pool to check.
- Returns:
Integrity status (0 if intact, non-zero if issues found).
-
void *get_pool(void *pool)
Retrieves the usable memory pointer of a pool.
- Parameters:
pool – Pointer to the pool.
- Returns:
Pointer to the pool’s usable memory.
-
int check()
Checks the overall integrity of the allocator.
- Returns:
Integrity status (0 if intact, non-zero if issues found).
-
StorageReport report() const
Generates a storage usage report.
- Returns:
StorageReport containing free space and fragmentation details.
-
void logStorageReport() const
Logs the storage usage report.
Public Static Functions
-
static void integrity_walker(void *ptr, size_t size, int used, void *user)
Walker function for integrity checks.
- Parameters:
ptr – Pointer to the block.
size – Size of the block in bytes.
used – Flag indicating if the block is used (non-zero) or free (0).
user – User-defined data passed to the walker.
Public Static Attributes
-
static size_t MAX_POOL = 5
Maximum number of memory pools allowed.
Private Functions
-
explicit eAlloc(void *mem, size_t bytes)
-
class ILockable
- #include <globalELock.hpp>
Abstract lockable interface for platform-agnostic mutexes.
All platform adapters must implement ILockable.
-
struct IntegrityResult
- #include <eAlloc.hpp>
Holds integrity check results.
-
class LockGuard
- #include <globalELock.hpp>
A universal RAII lock guard class that manages a lock’s lifetime.
This class provides a RAII-style mechanism to automatically acquire a lock upon construction and release it upon destruction. It wraps a reference to an ILockable object and attempts to acquire the lock using an optional timeout parameter. The lock is released in the destructor if it was successfully acquired.
Note
Copy construction and copy-assignment are disabled to prevent multiple ownership of the same lock.
- Param lock:
A reference to an ILockable object managing the lock.
- Param timeout_ms:
The timeout in milliseconds for acquiring the lock (default is 0xFFFFFFFF for no timeout).
-
template<typename U>
struct rebind - #include <StackAllocator.hpp>
Rebind template for allocator compatibility with different types.
- Template Parameters:
U – The new type to allocate.
-
struct SecondLevel
- #include <tlsf.hpp>
Second-level structure for the TLSF allocator.
This structure represents the second-level index in the Two-Level Segregated Fit allocator. It maintains a bitmap (sl_bitmap) that indicates which shelves (free lists) have available blocks, and an array of pointers (shelves) to the free block lists for blocks of specific size ranges.
-
template<typename T, size_t PoolSize>
class StackAllocator - #include <StackAllocator.hpp>
Standard C++ allocator interface using a stack-allocated buffer and TLSF.
Usage: dsa::StackAllocator<int, 1024> alloc; std::vector<int, dsa::StackAllocator<int, 1024>> v(alloc);
Thread Safety:
Not thread-safe by default.
To enable, call setLock() with a elock::ILockable* mutex adapter.
No STL bloat for MCU: lock is optional and not used unless set.
- Template Parameters:
T – Type of object to allocate.
PoolSize – Size of the internal stack buffer in bytes.
Standard C++ allocator typedefs
-
using size_type = size_t
Size type.
-
using difference_type = ptrdiff_t
Difference type.
Public Functions
-
inline StackAllocator()
Constructor initializes the stack allocator with a fixed-size buffer.
-
template<typename U>
inline StackAllocator(const StackAllocator<U, PoolSize>&) Copy constructor for allocator propagation (required by STL).
- Template Parameters:
U – Other type for rebind.
-
inline pointer allocate(size_type n)
Allocates uninitialized storage for n objects of type T.
- Parameters:
n – Number of objects to allocate.
- Throws:
std::bad_alloc – if allocation fails.
- Returns:
Pointer to the allocated storage.
-
inline void deallocate(pointer p, size_type)
Deallocates storage previously allocated by this allocator.
Note
The number of objects parameter is present for interface compliance but is not used by this specific deallocation function.
- Parameters:
p – Pointer to the memory to deallocate.
-
inline void construct(pointer p, const_reference val)
Constructs an object of type T at the given memory location.
- Parameters:
p – Pointer to memory.
val – Value to copy-construct.
-
inline void destroy(pointer p)
Destroys an object of type T at the given memory location.
- Parameters:
p – Pointer to object to destroy.
-
inline bool operator==(const StackAllocator &other) const
Equality operator: compares based on memory pool identity.
- Parameters:
other – Another StackAllocator instance.
- Returns:
True if using the same memory pool.
-
inline bool operator!=(const StackAllocator &other) const
Inequality operator.
- Parameters:
other – Another StackAllocator instance.
- Returns:
True if not using the same memory pool.
-
inline void setLock(elock::ILockable *lock)
Sets a lock for thread safety (optional, MCU/host agnostic).
If not set, the allocator is not thread-safe. For host builds, use elock::StdMutex. For embedded, use the appropriate platform adapter. Locking is delegated to eAlloc.
- Parameters:
lock – Pointer to a elock::ILockable mutex adapter.
-
struct StorageReport
- #include <eAlloc.hpp>
Reports storage usage statistics for the allocator.
This structure provides a summary of memory usage data including:
The total free memory available in bytes.
The size (in bytes) of the largest contiguous free memory block.
The count of free blocks within the allocator.
A fragmentation factor ranging from 0 (no fragmentation) to 1 (high fragmentation).
Use this report to monitor the efficiency and fragmentation of the allocator’s memory usage.
-
template<size_t SLI = 5>
class TLSF - #include <tlsf.hpp>
Public Types
-
typedef ptrdiff_t tlsfptr_t
Type for pointer arithmetic.
-
typedef void (*tlsf_walker)(void *ptr, size_t size, int used, void *user)
Function pointer type for walking memory blocks.
Public Static Functions
-
static inline size_t get_size(const BlockHeader *block)
Gets the usable size of a block.
This function returns the block size after masking out the flag bits.
- Parameters:
block – Pointer to the block header.
- Returns:
The size of the block.
-
static inline void set_size(BlockHeader *block, size_t size)
Sets the size of a block while preserving flag bits.
This function assigns the given size to the block header, preserving the current flag bits.
- Parameters:
block – Pointer to the block header.
size – New size to set.
-
static inline bool is_free(const BlockHeader *block)
Checks if a block is free.
- Parameters:
block – Pointer to the block header.
- Returns:
True if the block is free, false otherwise.
-
static inline bool is_prev_free(const BlockHeader *block)
Checks if the previous block is free.
- Parameters:
block – Pointer to the block header.
- Returns:
True if the previous block is free, false otherwise.
-
static inline bool is_last(const BlockHeader *block)
Checks if the block is the last block in the heap.
This is determined by checking if the block size is zero.
- Parameters:
block – Pointer to the block header.
- Returns:
True if the block is the last block, false otherwise.
-
static inline void set_free(BlockHeader *block)
Marks the block as free.
- Parameters:
block – Pointer to the block header.
-
static inline void set_used(BlockHeader *block)
Marks the block as used.
- Parameters:
block – Pointer to the block header.
-
static inline void set_prev_free(BlockHeader *block)
Marks the previous block as free.
- Parameters:
block – Pointer to the block header.
-
static inline void set_prev_used(BlockHeader *block)
Marks the previous block as used.
- Parameters:
block – Pointer to the block header.
-
static inline const void *to_ptr(const BlockHeader *block)
-
static inline void *to_ptr_nc(BlockHeader *block)
-
static inline const BlockHeader *from_ptr(const void *ptr)
-
static inline BlockHeader *from_ptr_nc(void *ptr)
-
static inline const BlockHeader *offset_to_block(const void *ptr, size_t size)
-
static inline BlockHeader *offset_to_block_nc(void *ptr, size_t size)
-
static inline BlockHeader *prev(const BlockHeader *block)
-
static inline BlockHeader *next(BlockHeader *block)
-
static inline const BlockHeader *next_const(const BlockHeader *block)
-
static inline BlockHeader *link_next(BlockHeader *block)
-
static inline void mark_as_free(BlockHeader *block)
-
static inline void mark_as_used(BlockHeader *block)
-
static inline size_t align_up(size_t x, size_t align)
-
static inline size_t align_down(size_t x, size_t align)
-
static inline void *align_ptr(const void *ptr, size_t align)
-
static inline size_t adjust_request_size(size_t size, size_t align)
Adjusts the requested allocation size to be aligned to the specified alignment and ensures it is not smaller than the minimum block size.
- Parameters:
size – The requested allocation size.
align – The required alignment.
- Returns:
The adjusted allocation size.
-
static inline void mapping_insert(size_t size, int *fli, int *sli)
Maps the given size to TLSF first-level (fli) and second-level (sli) indices.
For sizes smaller than SMALL_BLOCK_SIZE, the first-level index is set to 0, and the second-level index is computed based on the size. For larger sizes, the indices are computed using the most significant bit (via fls) with additional bit manipulations.
- Parameters:
size – The size to be mapped.
fli – Pointer to store the computed first-level index.
sli – Pointer to store the computed second-level index.
-
static inline void mapping_search(size_t size, int *fli, int *sli)
Rounds up the requested size and maps it to TLSF indices.
If the requested size is at least SMALL_BLOCK_SIZE, a rounding value is computed and added to the size. Then, mapping_insert is called to determine the corresponding TLSF indices.
- Parameters:
size – The requested allocation size.
fli – Pointer to store the computed first-level index.
sli – Pointer to store the computed second-level index.
-
static inline BlockHeader *search_suitable_block(Control *control, int *fli, int *sli)
Searches for a suitable free block in the TLSF allocator.
This function uses the provided first-level and second-level indices to locate a free block that is large enough to satisfy the allocation requirements. If no block is found in the current first-level list, the function searches in the next higher-level list.
- Parameters:
control – Pointer to the TLSF control structure.
fli – Pointer to the first-level index; updated during the search.
sli – Pointer to the second-level index; updated during the search.
- Returns:
Pointer to a free block that satisfies the criteria, or nullptr if none is found.
-
static inline void remove_free_block(Control *control, BlockHeader *block, int fl, int sl)
Removes a block from the free list.
Detaches the specified block from its free list by updating its previous and next pointers and adjusts the free list bitmaps corresponding to the first-level and second-level indices.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the block to be removed.
fl – The first-level index associated with the block.
sl – The second-level index associated with the block.
-
static inline void insert_free_block(Control *control, BlockHeader *block, int fl, int sl)
Inserts a block into the free list.
Adds the specified block into the free list at the given first-level and second-level indices, updating the free list pointers and associated bitmaps accordingly.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the block to be inserted.
fl – The first-level index where the block is to be inserted.
sl – The second-level index where the block is to be inserted.
-
static inline void remove(Control *control, BlockHeader *block)
-
static inline void insert(Control *control, BlockHeader *block)
-
static inline bool can_split(BlockHeader *block, size_t size)
Checks whether a block can be split into two blocks.
This function verifies if the given block’s size is large enough to be divided into a block of the desired size plus the overhead required for the block header.
- Parameters:
block – Pointer to the block header to check.
size – The desired size for the first block after splitting.
- Returns:
True if the block can be split; false otherwise.
-
static inline BlockHeader *split(BlockHeader *block, size_t size)
Splits a block into two parts.
The function reduces the size of the original block to the requested size and creates a remaining block from the leftover space. It ensures that the remaining block is properly aligned and meets the minimum block size requirement.
- Parameters:
block – Pointer to the original block header.
size – The size for the allocated portion of the block.
- Returns:
Pointer to the remaining block after the split.
-
static inline BlockHeader *absorb(BlockHeader *prev, BlockHeader *block)
Absorbs the second block into the first.
Merges a block with its successor by adding the size of the second block (plus header overhead) to the first block and relinking the next block.
- Parameters:
prev – Pointer to the preceding block which will absorb the next block.
block – Pointer to the block to be absorbed.
- Returns:
Pointer to the updated block after absorption.
-
static inline BlockHeader *merge_prev(Control *control, BlockHeader *block)
Merges the current block with its previous free neighbor.
If the previous physical block is free, it is removed from the free list and merged with the current block.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the current block header.
- Returns:
Pointer to the merged block.
-
static inline BlockHeader *merge_next(Control *control, BlockHeader *block)
Merges the current block with its next free neighbor.
If the next physical block is free, it is removed from the free list and merged with the current block.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the current block header.
- Returns:
Pointer to the merged block.
-
static inline void trim_free(Control *control, BlockHeader *block, size_t size)
Trims a free block to a specified size.
If the free block is large enough to be split, this function splits the block, adjusts the next block pointer, marks the remaining block as free, and inserts it into the free list.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the free block to trim.
size – The desired allocation size.
-
static inline void trim_used(Control *control, BlockHeader *block, size_t size)
Trims a used block to the specified allocation size.
If the used block can be split, this function divides the block, marks the remaining part as used, merges it with the next free block if possible, and reinserts it into the free list.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the used block to trim.
size – The requested allocation size.
-
static inline BlockHeader *trim_free_leading(Control *control, BlockHeader *block, size_t size)
Trims the leading portion of a free block.
Splits off a leading segment from a free block, adjusts pointers accordingly, and inserts the remainder back into the free list.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the original free block.
size – The desired size for the leading segment.
- Returns:
Pointer to the remaining block after trimming.
-
static inline BlockHeader *locate_free(Control *control, size_t size)
Locates a free block of sufficient size from the free list.
Searches for a free block that meets or exceeds the requested size and removes it from the free list.
- Parameters:
control – Pointer to the TLSF control structure.
size – The minimum required block size.
- Returns:
Pointer to a suitable free block, or null if none is found.
-
static inline void *prepare_used(Control *control, BlockHeader *block, size_t size)
Prepares a free block for allocation by marking it as used.
Trims the block to the requested size, marks it as used, and returns a pointer to the usable memory region. If the block is null, this function returns null.
- Parameters:
control – Pointer to the TLSF control structure.
block – Pointer to the free block to prepare.
size – The desired allocation size.
- Returns:
Pointer to the allocated memory, or null if block is null.
-
static inline void initialise_control(Control *control)
Initializes the TLSF allocator control structure.
Sets up the initial state of the allocator, including the free list pointers and bitmaps.
- Parameters:
control – Pointer to the control structure to initialize.
-
static inline void default_walker(void *ptr, size_t size, int used, void *user)
Default walker callback function.
This function is used as a default callback for iterating over memory blocks.
- Parameters:
ptr – Pointer to the memory block.
size – The size of the memory block in bytes.
used – Flag indicating if the block is used (non-zero) or free (zero).
user – User-defined parameter for callback context.
-
static inline int check(Control *control)
Checks the consistency of the free lists and bitmaps in the TLSF allocator.
This function iterates over all cabinets and shelves in the control structure to verify that the free lists and associated bitmaps accurately reflect the state of the allocator.
- Parameters:
control – The TLSF control structure.
- Returns:
An integer status code (0 indicates success).
-
static inline size_t cabinets()
Returns the number of first-level indices (cabinets) in the allocator.
-
static inline size_t shelves()
Returns the number of shelves per cabinet.
-
static inline size_t total_shelves()
Returns the total number of shelves in the allocator.
-
static inline size_t size()
Returns the size of the allocator’s control structure.
-
static inline size_t align_size()
Returns the alignment size used by the allocator.
-
static inline size_t min_block_size()
Returns the minimum allowable block size.
-
static inline size_t max_block_size()
Returns the maximum allowable block size.
-
static inline size_t pool_overhead()
Returns the overhead (in bytes) of the memory pool due to allocator internal bookkeeping.
-
static inline size_t alloc_overhead()
Returns the overhead (in bytes) incurred during each allocation.
-
static inline size_t block_size(void *ptr)
Returns the block size in bytes.
Private Static Attributes
-
static size_t ALIGN_SIZE_LOG2 = 2
-
static size_t BLOCK_ALIGNMENT = (1 << ALIGN_SIZE_LOG2)
-
static size_t FL_INDEX_MAX = 31
-
static size_t SLI_COUNT = (1 << SL_INDEX_LOG2)
-
static size_t FL_INDEX_SHIFT = (SL_INDEX_LOG2 + ALIGN_SIZE_LOG2)
-
static size_t FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1)
-
static size_t SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT)
-
static size_t ALIGN_SIZE = BLOCK_ALIGNMENT
-
static size_t free_bit = 1 << 0
-
static size_t prev_free_bit = 1 << 1
-
static size_t flag_mask = prev_free_bit | free_bit
-
static size_t block_header_overhead = sizeof(size_t)
-
static size_t block_start_offset = offsetof(BlockHeader, size_and_flags) + block_header_overhead
-
static size_t block_size_min = sizeof(BlockHeader) - sizeof(BlockHeader*)
-
static size_t block_size_max = static_cast<size_t>(1 << FL_INDEX_MAX)
-
typedef ptrdiff_t tlsfptr_t
-
namespace dsa
-
namespace elock
- file builtins.h
Portable bit manipulation intrinsics (ffs/fls) with architecture-specific optimizations.
Provides fast find-first-set (ffs) and find-last-set (fls) implementations for GCC, MSVC, ARM, and generic fallback.
Use dsa_decl ffs(unsigned int) and fls(unsigned int) for portable, inlined bit scanning.
Selects the best implementation for the detected compiler/architecture.
- file eAlloc.cpp
- #include “eAlloc.hpp”
Implementation of TLSF-based MCU/host-agnostic memory allocator (dsa::eAlloc).
See eAlloc.hpp for API, usage, and thread safety notes.
- file eAlloc.hpp
- #include “Logger.hpp”#include “tlsf.hpp”#include “globalELock.hpp”
TLSF-based MCU/host-agnostic memory allocator with multi-pool support.
Provides efficient, deterministic allocation and deallocation with minimal fragmentation. Supports multiple memory pools, alignment, reallocation, and MCU/host-agnostic locking via elock.
Usage:
Use dsa::eAlloc for all heap management (malloc/free, STL, or custom allocators).
For thread safety, call setLock() with a elock::ILockable* mutex adapter.
Add or remove pools as needed for flexible memory regions.
Thread Safety:
Not thread-safe by default. To enable, set a elock (see globalELock.hpp).
Only one elock per allocator instance is recommended.
- file globalELock.hpp
- #include <stdint.h>
Universal RAII lock guard and platform lock adapter system for eAlloc.
Provides MCU-agnostic, minimal-overhead locking for critical sections and memory allocators. Selects the appropriate mutex adapter for each platform via CMake and preprocessor macros.
Usage:
Use elock::ILockable as the abstract mutex interface.
Use elock::LockGuard for RAII critical sections.
Use the correct adapter (e.g. elock::FreeRTOSMutex, elock::StdMutex) for your platform.
Platform is selected by CMake option and macro (EALLOC_PC_HOST, FREERTOS, etc).
Thread Safety:
Only one lock per memory pool/allocator instance is recommended.
Avoid double-locking by letting the allocator own the lock and exposing setLock().
No STL bloat for MCU: STL headers only included for PC/host builds.
- file StackAllocator.hpp
- #include “eAlloc.hpp”#include <cstddef>#include <stdexcept>
MCU/host-agnostic C++ allocator using a stack-allocated memory pool and TLSF.
This allocator is suitable for embedded and host builds, provides minimal STL usage, and supports optional thread safety via elock::ILockable. It is intended for use with STL containers or custom allocation needs where a fixed-size stack buffer is desired.
- file tlsf.hpp
- #include “builtins.h”#include <assert.h>#include <climits>#include <cstdint>#include <cstdlib>#include <cstring>#include <memory>
- group Bit Manipulation Intrinsics
- dir src