Files
common/memory_manager.h
2026-05-03 23:20:16 -07:00

282 lines
6.8 KiB
C++

#ifndef MEMORY_MANAGER_H
#define MEMORY_MANAGER_H
#include <stdint.h>
#include <stddef.h>
#ifdef ARDUINO
#include <Arduino.h>
#else
#include <cstdlib>
#include <memory>
#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<typename T>
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<T*>(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<typename T>
SmartPtr<T> makeSmartPtr(MemoryPool* pool = &globalMemoryPool) {
return SmartPtr<T>(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