282 lines
6.8 KiB
C++
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
|