#ifndef MEMORY_MANAGER_H #define MEMORY_MANAGER_H #include #include #ifdef ARDUINO #include #else #include #include #endif /** * @brief Memory pool for embedded systems with limited heap * * This class provides a simple memory pool implementation to avoid * heap fragmentation and provide predictable memory allocation. */ class MemoryPool { private: static const size_t POOL_SIZE = 4096; // 4KB pool static const size_t MAX_BLOCKS = 32; struct Block { void* ptr; size_t size; bool in_use; uint32_t magic; // For corruption detection }; uint8_t pool_memory[POOL_SIZE]; Block blocks[MAX_BLOCKS]; size_t next_free_offset; uint32_t allocation_count; uint32_t deallocation_count; static const uint32_t MAGIC_NUMBER = 0xDEADBEEF; public: MemoryPool(); ~MemoryPool(); /** * @brief Allocate memory from the pool * @param size Size in bytes to allocate * @return Pointer to allocated memory or nullptr if failed */ void* allocate(size_t size); /** * @brief Deallocate memory back to the pool * @param ptr Pointer to memory to deallocate * @return true if successful, false if invalid pointer */ bool deallocate(void* ptr); /** * @brief Get memory usage statistics */ struct MemoryStats { size_t total_size; size_t used_size; size_t free_size; uint32_t allocations; uint32_t deallocations; uint32_t active_blocks; }; MemoryStats getStats() const; /** * @brief Check for memory corruption * @return true if memory is intact, false if corruption detected */ bool checkIntegrity() const; /** * @brief Reset the entire pool (use with caution!) */ void reset(); /** * @brief Print memory usage information */ void printStats() const; }; /** * @brief RAII wrapper for automatic memory management * * This template class provides automatic memory management * using RAII principles for embedded systems. */ template class SmartPtr { private: T* ptr_; MemoryPool* pool_; bool owns_memory_; public: /** * @brief Constructor for pool-allocated memory */ explicit SmartPtr(MemoryPool* pool = nullptr) : ptr_(nullptr), pool_(pool), owns_memory_(false) { if (pool_) { ptr_ = static_cast(pool_->allocate(sizeof(T))); if (ptr_) { new(ptr_) T(); // Placement new owns_memory_ = true; } } } /** * @brief Constructor taking ownership of existing pointer */ SmartPtr(T* ptr, MemoryPool* pool, bool owns = true) : ptr_(ptr), pool_(pool), owns_memory_(owns) {} /** * @brief Move constructor */ SmartPtr(SmartPtr&& other) noexcept : ptr_(other.ptr_), pool_(other.pool_), owns_memory_(other.owns_memory_) { other.ptr_ = nullptr; other.owns_memory_ = false; } /** * @brief Move assignment operator */ SmartPtr& operator=(SmartPtr&& other) noexcept { if (this != &other) { reset(); ptr_ = other.ptr_; pool_ = other.pool_; owns_memory_ = other.owns_memory_; other.ptr_ = nullptr; other.owns_memory_ = false; } return *this; } /** * @brief Destructor - automatically cleans up */ ~SmartPtr() { reset(); } /** * @brief Delete copy constructor and assignment (no copying) */ SmartPtr(const SmartPtr&) = delete; SmartPtr& operator=(const SmartPtr&) = delete; /** * @brief Access the managed object */ T* get() const { return ptr_; } T& operator*() const { return *ptr_; } T* operator->() const { return ptr_; } /** * @brief Check if the pointer is valid */ bool isValid() const { return ptr_ != nullptr; } explicit operator bool() const { return isValid(); } /** * @brief Release ownership without destroying */ T* release() { T* temp = ptr_; ptr_ = nullptr; owns_memory_ = false; return temp; } /** * @brief Reset the pointer, destroying current object if owned */ void reset() { if (ptr_ && owns_memory_) { ptr_->~T(); // Explicit destructor call if (pool_) { pool_->deallocate(ptr_); } } ptr_ = nullptr; owns_memory_ = false; } }; /** * @brief Buffer management class with bounds checking */ class SafeBuffer { private: uint8_t* data_; size_t size_; size_t capacity_; MemoryPool* pool_; bool owns_memory_; public: SafeBuffer(size_t capacity, MemoryPool* pool = nullptr); ~SafeBuffer(); // Delete copy constructor and assignment SafeBuffer(const SafeBuffer&) = delete; SafeBuffer& operator=(const SafeBuffer&) = delete; // Move constructor and assignment SafeBuffer(SafeBuffer&& other) noexcept; SafeBuffer& operator=(SafeBuffer&& other) noexcept; /** * @brief Write data to buffer with bounds checking */ bool write(const void* data, size_t size, size_t offset = 0); /** * @brief Read data from buffer with bounds checking */ bool read(void* data, size_t size, size_t offset = 0) const; /** * @brief Append data to buffer */ bool append(const void* data, size_t size); /** * @brief Clear buffer contents */ void clear(); /** * @brief Get buffer information */ uint8_t* data() { return data_; } const uint8_t* data() const { return data_; } size_t size() const { return size_; } size_t capacity() const { return capacity_; } size_t available() const { return capacity_ - size_; } /** * @brief Check if buffer is valid */ bool isValid() const { return data_ != nullptr; } }; // Global memory pool instance extern MemoryPool globalMemoryPool; /** * @brief Convenience function to create smart pointers */ template SmartPtr makeSmartPtr(MemoryPool* pool = &globalMemoryPool) { return SmartPtr(pool); } /** * @brief Memory debugging macros (only active in debug builds) */ #ifdef DEBUG_MEMORY #define MEM_ALLOC(size) globalMemoryPool.allocate(size) #define MEM_FREE(ptr) globalMemoryPool.deallocate(ptr) #define MEM_CHECK() globalMemoryPool.checkIntegrity() #define MEM_STATS() globalMemoryPool.printStats() #else #define MEM_ALLOC(size) globalMemoryPool.allocate(size) #define MEM_FREE(ptr) globalMemoryPool.deallocate(ptr) #define MEM_CHECK() true #define MEM_STATS() do {} while(0) #endif #endif // MEMORY_MANAGER_H